diff options
| author | Jules Laplace <julescarbon@gmail.com> | 2017-09-26 00:21:27 +0200 |
|---|---|---|
| committer | Jules Laplace <julescarbon@gmail.com> | 2017-09-26 00:21:27 +0200 |
| commit | 73cbc66bb96b348ec791e6854d6c24e6d85b2fa8 (patch) | |
| tree | d06eddeec93e692fde63cde5b21a20ff623f1386 /StoneIsland/plugins/cordova-plugin-firebase/src/ios/Firebase/Crash | |
| parent | 3be2b3aea204f145d6e7c98d835891947105ed0e (diff) | |
cordova-plugin-firebase
Diffstat (limited to 'StoneIsland/plugins/cordova-plugin-firebase/src/ios/Firebase/Crash')
11 files changed, 1264 insertions, 0 deletions
diff --git a/StoneIsland/plugins/cordova-plugin-firebase/src/ios/Firebase/Crash/FirebaseCrash.framework/FirebaseCrash b/StoneIsland/plugins/cordova-plugin-firebase/src/ios/Firebase/Crash/FirebaseCrash.framework/FirebaseCrash Binary files differnew file mode 100755 index 00000000..7cf08c10 --- /dev/null +++ b/StoneIsland/plugins/cordova-plugin-firebase/src/ios/Firebase/Crash/FirebaseCrash.framework/FirebaseCrash diff --git a/StoneIsland/plugins/cordova-plugin-firebase/src/ios/Firebase/Crash/FirebaseCrash.framework/Headers/FIRCrashLog.h b/StoneIsland/plugins/cordova-plugin-firebase/src/ios/Firebase/Crash/FirebaseCrash.framework/Headers/FIRCrashLog.h new file mode 100755 index 00000000..ac446a62 --- /dev/null +++ b/StoneIsland/plugins/cordova-plugin-firebase/src/ios/Firebase/Crash/FirebaseCrash.framework/Headers/FIRCrashLog.h @@ -0,0 +1,164 @@ +#import <Foundation/Foundation.h> + +NS_ASSUME_NONNULL_BEGIN + +/** + * @abstract Logs a message to the Firebase Crash Reporter system. + * + * @discussion This method adds a message to the crash reporter + * logging system. The recent logs will be sent with the crash + * report when the application exits abnormally. Note that the + * timestamp of this message and the timestamp of the console + * message may differ by a few milliseconds. + * + * Messages should be brief as the total size of the message payloads + * is limited by the uploader and may change between releases of the + * crash reporter. Excessively long messages will be truncated + * safely but that will introduce a delay in submitting the message. + * + * @warning Raises an NSInvalidArgumentException if @p format is nil. + * + * @param format A format string. + * + * @param ap A variable argument list. + */ +FOUNDATION_EXTERN NS_FORMAT_FUNCTION(1, 0) +void FIRCrashLogv(NSString *format, va_list ap); + +/** + * @abstract Logs a message to the Firebase Crash Reporter system. + * + * @discussion This method adds a message to the crash reporter + * logging system. The recent logs will be sent with the crash + * report when the application exits abnormally. Note that the + * timestamp of this message and the timestamp of the console + * message may differ by a few milliseconds. + * + * Messages should be brief as the total size of the message payloads + * is limited by the uploader and may change between releases of the + * crash reporter. Excessively long messages will be truncated + * safely but that will introduce a delay in submitting the message. + * + * @warning Raises an NSInvalidArgumentException if @p format is nil. + * + * @param format A format string. + * + * @param ... A comma-separated list of arguments to substitute into + * format. + * + * @see FIRCrashLogv(format, ap) + */ +FOUNDATION_STATIC_INLINE NS_FORMAT_FUNCTION(1, 2) +void FIRCrashLog(NSString *format, ...) { + va_list ap; + + va_start(ap, format); + FIRCrashLogv(format, ap); + va_end(ap); +} + +/** + * @abstract Logs a message to the Firebase Crash Reporter system as + * well as <code>NSLog()</code>. + * + * @discussion This method adds a message to the crash reporter + * logging system. The recent logs will be sent with the crash + * report when the application exits abnormally. Note that the + * timestamp of this message and the timestamp of the console + * message may differ by a few milliseconds. + * + * Messages should be brief as the total size of the message payloads + * is limited by the uploader and may change between releases of the + * crash reporter. Excessively long messages will be truncated + * safely but that will introduce a delay in submitting the message. + * + * @warning Raises an NSInvalidArgumentException if @p format is nil. + * + * @param format A format string. + * + * @param ap A variable argument list. + */ +FOUNDATION_STATIC_INLINE NS_FORMAT_FUNCTION(1, 0) +void FIRCrashNSLogv(NSString *format, va_list ap) { + va_list ap2; + + va_copy(ap2, ap); + NSLogv(format, ap); + FIRCrashLogv(format, ap2); + va_end(ap2); +} + +/** + * @abstract Logs a message to the Firebase Crash Reporter system as + * well as <code>NSLog()</code>. + * + * @discussion This method adds a message to the crash reporter + * logging system. The recent logs will be sent with the crash + * report when the application exits abnormally. Note that the + * timestamp of this message and the timestamp of the console + * message may differ by a few milliseconds. + * + * Messages should be brief as the total size of the message payloads + * is limited by the uploader and may change between releases of the + * crash reporter. Excessively long messages will be truncated + * safely but that will introduce a delay in submitting the message. + * + * @warning Raises an NSInvalidArgumentException if @p format is nil. + * + * @param format A format string. + * + * @param ... A comma-separated list of arguments to substitute into + * format. + * + * @see FIRCrashLogv(format, ap) + */ +FOUNDATION_STATIC_INLINE NS_FORMAT_FUNCTION(1, 2) +void FIRCrashNSLog(NSString *format, ...) { + va_list ap; + + va_start(ap, format); + FIRCrashNSLogv(format, ap); + va_end(ap); +} + +/** + * @abstract Logs a message to the Firebase Crash Reporter system in + * a way that is easily called from Swift code. + * + * @discussion This method adds a message to the crash reporter + * logging system. Similar to FIRCrashLog, but with a call signature + * that is more Swift friendly. Unlike FIRCrashLog, callers + * use string interpolation instead of formatting arguments. + * + * @code + * public func mySwiftFunction() { + * let unexpected_number = 10; + * FIRCrashMessage("This number doesn't seem right: \(unexpected_number)"); + * } + * @endcode + * + * Messages should be brief as the total size of the message payloads + * is limited by the uploader and may change between releases of the + * crash reporter. Excessively long messages will be truncated + * safely but that will introduce a delay in submitting the message. + * + * @param Message A log message + * + * @see FIRCrashLog(format, ...) + */ +FOUNDATION_STATIC_INLINE +void FIRCrashMessage(NSString *message) { + FIRCrashLog(@"%@", message); +} + +NS_ASSUME_NONNULL_END + +#ifdef FIRCRASH_REPLACE_NSLOG +#if defined(DEBUG) || defined(FIRCRASH_LOG_TO_CONSOLE) +#define NSLog(...) FIRCrashNSLog(__VA_ARGS__) +#define NSLogv(...) FIRCrashNSLogv(__VA_ARGS__) +#else +#define NSLog(...) FIRCrashLog(__VA_ARGS__) +#define NSLogv(...) FIRCrashLogv(__VA_ARGS__) +#endif +#endif diff --git a/StoneIsland/plugins/cordova-plugin-firebase/src/ios/Firebase/Crash/FirebaseCrash.framework/Headers/FirebaseCrash.h b/StoneIsland/plugins/cordova-plugin-firebase/src/ios/Firebase/Crash/FirebaseCrash.framework/Headers/FirebaseCrash.h new file mode 100755 index 00000000..18659214 --- /dev/null +++ b/StoneIsland/plugins/cordova-plugin-firebase/src/ios/Firebase/Crash/FirebaseCrash.framework/Headers/FirebaseCrash.h @@ -0,0 +1 @@ +#import "FIRCrashLog.h" diff --git a/StoneIsland/plugins/cordova-plugin-firebase/src/ios/Firebase/Crash/FirebaseCrash.framework/Modules/module.modulemap b/StoneIsland/plugins/cordova-plugin-firebase/src/ios/Firebase/Crash/FirebaseCrash.framework/Modules/module.modulemap new file mode 100755 index 00000000..537a790a --- /dev/null +++ b/StoneIsland/plugins/cordova-plugin-firebase/src/ios/Firebase/Crash/FirebaseCrash.framework/Modules/module.modulemap @@ -0,0 +1,12 @@ +framework module FirebaseCrash { + umbrella header "FirebaseCrash.h" + export * + module * { export *} + link "sqlite3" + link "z" + link framework "CoreGraphics" + link framework "CoreTelephony" + link framework "Foundation" + link framework "SystemConfiguration" + link framework "UIKit" +}
\ No newline at end of file diff --git a/StoneIsland/plugins/cordova-plugin-firebase/src/ios/Firebase/Crash/Protobuf.framework/Protobuf b/StoneIsland/plugins/cordova-plugin-firebase/src/ios/Firebase/Crash/Protobuf.framework/Protobuf Binary files differnew file mode 100644 index 00000000..546e02ec --- /dev/null +++ b/StoneIsland/plugins/cordova-plugin-firebase/src/ios/Firebase/Crash/Protobuf.framework/Protobuf diff --git a/StoneIsland/plugins/cordova-plugin-firebase/src/ios/Firebase/Crash/batch-upload b/StoneIsland/plugins/cordova-plugin-firebase/src/ios/Firebase/Crash/batch-upload new file mode 100755 index 00000000..053a3ee7 --- /dev/null +++ b/StoneIsland/plugins/cordova-plugin-firebase/src/ios/Firebase/Crash/batch-upload @@ -0,0 +1,416 @@ +#!/bin/bash + +usage () { + echo >&2 "usage: ${0##*/} [-hv] [-p google-service] [-i info] service-account-file {mach-o file|uuid} ..." +} + +help () { + usage + cat >&2 <<EOF + +-h Show this help. +-p Location of GoogleService-Info.plist. +-i Location of Info.plist. +-v Be verbose. + +account JSON file containing account information. +mach-o A path to an executable, dSYM file, library, + or other Mach-O object. +uuid A dSYM file's UUID (searches for the file). + +Processes one or more Mach-O files for use with the Firebase Crash +Reporter. dSYM bundles may be specified by full path to the dSYM +companion file (usually found under "DWARF") or by UUID. + +For applications and frameworks, please use the full path to the +Mach-O file. For frameworks, this will be "Blah.framework/Blah". +For applications, this will be "Blah.app/Blah". + +Useful environment variables: + + SERVICE_PLIST - path to GoogleService-Info.plist (-p command-line option) + INFO_PLIST - path to Info.plist (-i command-line option) + DUMP_SYMS - path to dump_syms executable + FCR_BUNDLE_ID - CFBundleIdentifier (build version) from Info.plist + FCR_PROD_VERS - CFBundleShortVersionString from Info.plist + FIREBASE_API_KEY - API key from GoogleService-Info.plist + FIREBASE_APP_ID - App ID from GoogleService-Info.plist + SWIFT_DEMANGLE - path to swift-demangle executable + +Setting any of the above prevents this script from searching for the +values. Specifically, the SERVICE_PLIST and INFO_PLIST files are not +required if FCR_* and FIREBASE_* environment variables are not empty. + +EOF +} + +KEEP_TEMPORARIES=false # mostly for debugging (not documented) + +while getopts hi:kp:v-: OPT; do + case ${OPT} in + h) help; exit 0;; + i) INFO_PLIST="${OPTARG}";; + k) KEEP_TEMPORARIES=true;; + p) SERVICE_PLIST="${OPTARG}";; + v) ((VERBOSE+=1));; + -) case "${OPTARG}" in + help) help; exit 0;; + info=*) INFO_PLIST="${OPTARG#info=}";; + service=*) SERVICE_PLIST="${OPTARG#service=}";; + verbose) ((VERBOSE+=1));; + *) usage; exit 2;; + esac;; + ?) usage; exit 2;; + esac +done + +shift $((OPTIND - 1)) + +. "$(dirname "$0")/upload-sym-util.bash" + +var_check () { + for VAR; do + if [[ "${!VAR}" =~ \$\(.*\) ]]; then + xcwarning "${VAR} (== \"${!VAR}\") appears to have unexpanded variables." + xcnote "Consider specifying it through an environment variable." + fi + done +} + +SERVICE_ACCOUNT_FILE="$1" + +if [[ ! -f "${SERVICE_ACCOUNT_FILE}" ]]; then + xcwarning "The first argument does not look like a service account file." + xcdebug "Will attempt to extract account file from legacy cache." + unset SERVICE_ACCOUNT_FILE +else + shift +fi + +if (( $# == 0 )); then + usage + exit 2 +fi + +if [[ "${INFO_PLIST}" && -f "${INFO_PLIST%/*}/GoogleService-Info.plist" ]]; then + : "${SERVICE_PLIST:="${INFO_PLIST%/*}/GoogleService-Info.plist"}" +fi + +if [[ "${SERVICE_PLIST}" && -f "${SERVICE_PLIST%/*}/Info.plist" ]]; then + : "${INFO_PLIST:="${SERVICE_PLIST%/*}/Info.plist"}" +fi + +xcdebug "SERVICE_PLIST = ${SERVICE_PLIST:="$(find . -name GoogleService-Info.plist | head -n1)"}" + +xcdebug "INFO_PLIST = ${INFO_PLIST:="$(find . -name Info.plist | head -n1)"}" + +if [[ -f "${SERVICE_PLIST}" ]]; then + xcdebug "FIREBASE_API_KEY = ${FIREBASE_API_KEY:="$(/usr/libexec/PlistBuddy -c 'print API_KEY' "${SERVICE_PLIST}")"}" + xcdebug "FIREBASE_APP_ID = ${FIREBASE_APP_ID:="$(/usr/libexec/PlistBuddy -c 'print GOOGLE_APP_ID' "${SERVICE_PLIST}")"}" + xcdebug "FCR_BUNDLE_ID = ${FCR_BUNDLE_ID:="$(/usr/libexec/PlistBuddy -c 'print BUNDLE_ID' "${SERVICE_PLIST}")"}" +fi + +if [[ -f "${INFO_PLIST}" ]]; then + xcdebug "FCR_PROD_VERS = ${FCR_PROD_VERS:="$(/usr/libexec/PlistBuddy -c 'print CFBundleShortVersionString' "${INFO_PLIST}" 2>/dev/null)"}" +fi + +var_check FCR_PROD_VERS FCR_BUNDLE_ID + +ERROR=$'environment variable empty or unset\n\nExplicitly add to environment or set GoogleService-Info.plist (-p)\nand Info.plist (-i) flags to extract values from the files.\n\nTry "'"$0"' -h" for details.' + +: "${FIREBASE_API_KEY:?"${ERROR}"}" "${FIREBASE_APP_ID:?"${ERROR}"}" +: "${FCR_PROD_VERS:?"${ERROR}"}" "${FCR_BUNDLE_ID:?"${ERROR}"}" + +# Extract key from legacy cache. + +if [[ ! "${SERVICE_ACCOUNT_FILE}" ]]; then + xcwarning "Running extract-keys on desktop." + EXTRACT_KEYS="$(script_dir)/extract-keys" + (cd "${HOME}/Desktop"; "${EXTRACT_KEYS}") || exit $? + SERVICE_ACCOUNT_FILE="${HOME}/Desktop/${FIREBASE_APP_ID}.json" + xcdebug "Using ${SERVICE_ACCOUNT_FILE} as account file. Please move this and all other extracted keys to a safe place." +fi + +if [[ ! -f "${SERVICE_ACCOUNT_FILE}" ]]; then + echo >&2 "Unable to find service account file." + echo >&2 + usage + exit 2 +fi + +# usage: extract_symbols_and_upload *dwarf-file* *arch* *exe-file* +# +# Do NOT use the dSYM bundle path. While it may work on occasion, it +# is not guaranteed to do so; the full path to the DWARF companion +# file will always work. (Discovered by Kerem Erkan.) +# +# If the executable is empty, use the DWARF companion file as a proxy +# for the executable. +extract_symbols_and_upload () { + local DWARF_COMPANION="$1" ARCH="$2" EXECUTABLE="$3" + + if [[ ! "${EXECUTABLE}" ]]; then + xcdebug "No executable; using ${DWARF_COMPANION} as symbol source." + + EXECUTABLE="${DWARF_COMPANION}" + unset DWARF_COMPANION + fi + + [[ "${EXECUTABLE}" ]] || return 1 + + if [[ -x "${SWIFT_DEMANGLE:=$(xcrun --find swift-demangle 2>/dev/null)}" ]]; + then + SWIFT_DEMANGLE_COMMAND="${SWIFT_DEMANGLE} -simplified" + else + SWIFT_DEMANGLE_COMMAND=/bin/cat + fi + fcr_mktemp SYMBOL_FILE + + "${DUMP_SYMS:="$(script_dir)/dump_syms"}" -a "${ARCH}" ${DWARF_COMPANION:+-g "${DWARF_COMPANION}"} "${EXECUTABLE}" | ${SWIFT_DEMANGLE_COMMAND} >|"${SYMBOL_FILE}" || return $? + + fcr_upload_files "${SYMBOL_FILE}" || return $? +} + +# usage: is_executable *path* +# +# Check to see if the file is an executable or a dSYM bundle +is_executable () { + [[ -f "$1" || ( -d "$1" && "${1%/}" == *.dSYM ) ]] +} + +# usage: is_uuid *string* +# +# Verify that the argument is a UUID. +is_uuid () { + [[ "$1" =~ ^[[:xdigit:]]{8}-[[:xdigit:]]{4}-[[:xdigit:]]{4}-[[:xdigit:]]{4}-[[:xdigit:]]{12}$ ]] +} + +# usage: set_uuids_archs *mach-o-file* +# +# side effect: appends to UUIDS, ARCHS +# +# Extract the uuid and architecture information from the given Mach-O +# file and append the information to the UUIDS and ARCHS arrays. +set_uuids_archs () { + eval "$(dwarfdump --uuid "$1" | awk '/^UUID:/ { print "UUIDS+=(" $2 "); ARCHS+=" $3 }')" +} + +# usage: mdls_to_bash +# +# Convert the output of mdls to a string consumable by bash. mdls +# outputs string arrays as quoted strings separated by commas, and +# Unicode characters as '\Uxxxx'. +# +# Note: this is sensitive to the current locale. If the locale is not +# UTF-8, then wide-character warnings will result if the strings +# contain non-ASCII characters. This is actually a desired behavior, +# because bash has issues with non-Unicode encodings for file names. +# (The macOS default is to have UTF-8 enabled, so this should not be a +# problem for the majority of use cases.) +mdls_to_bash () { + perl -C -ple 's/,$//; s/\\U(....)/chr hex $1/ge' +} + +for EXE; do + if is_executable "${EXE}"; then + xcdebug "Assuming ${EXE} is an executable or dSYM bundle." + + # Import architecture UUID information + UUIDS=() ARCHS=() + set_uuids_archs "${EXE}" + + for I in "${!UUIDS[@]}"; do + xcdebug "Found ${UUIDS[$I]} for ${ARCHS[$I]} in ${EXE}" + done + + if ((${#UUIDS[*]} == 0)); then + xcwarning "${EXE} exists, but has no architecture information." + continue + fi + + if [[ "${EXE}" = *.dSYM ]]; then + xcdebug "Removing dSYM bundle as executable target." + unset EXE + fi + + elif is_uuid "${EXE}"; then + xcdebug "${EXE} looks like a UUID to me." + UUIDS=("${EXE}"); unset EXE + + else + xcwarning "${EXE}: not an executable, bundle, or UUID." + continue + fi + + BUNDLES=() + + for UUID in "${UUIDS[@]}"; do + xcdebug "Searching for ${UUID} ..." + + QUERY_UUID="com_apple_xcode_dsym_uuids == '${UUID}'" + QUERY_TYPE="kMDItemContentType == 'com.apple.xcode.dsym' || kMDItemContentType == 'com.apple.xcode.archive'" + QUERY="(${QUERY_UUID}) && (${QUERY_TYPE})" + + if ((VERBOSE > 1)); then + xcnote "Passing query \"${QUERY}\" to mdfind." + fi + + MD_FIND_RESULT=() + + eval "$(mdfind "${QUERY}" -0 | xargs -0 perl -le 'print "MD_FIND_RESULT+=(\Q$_\E)" for @ARGV')" + + xcdebug "mdfind returned (${MD_FIND_RESULT[*]})" + + # BUNDLES should contain no duplicates. + for I in "${!MD_FIND_RESULT[@]}"; do + for BUNDLE in "${BUNDLES[@]}"; do + if [[ "${MD_FIND_RESULT[$I]}" == "$BUNDLE" ]]; then + unset "MD_FIND_RESULT[$I]" + fi + done + done + + BUNDLES+=("${MD_FIND_RESULT[@]}") + done + + if [[ ${#BUNDLES[@]} == 0 && ${#ARCHS[@]} == 0 ]]; then + xcwarning "No executable or bundle found for ${UUIDS[*]}." + xcnote "Try passing in the executable itself instead of a UUID." + continue + fi + + xcdebug "BUNDLES = (${BUNDLES[*]})" + + if [[ ${#BUNDLES[@]} == 0 ]]; then + xcdebug "No dSYM bundle found." + + # The dSYM has to be on a normal volume (not temporary). It + # can, however, be shared among multiple executables. + if [[ ! "${SCRATCH_BUNDLE}" ]]; then + SCRATCH_BUNDLE="${HOME}/com.google.BatchUploadScratchFile.dSYM" + FCR_TEMPORARY_FILES+=("${SCRATCH_BUNDLE}") + fi + + xcdebug "Creating one in ${SCRATCH_BUNDLE}" + + BUNDLES=("${SCRATCH_BUNDLE}") + + # Create the dSYM bundle. This may produce an empty dSYM + # bundle if the executable has no debugging information. + xcrun dsymutil -o "${BUNDLES[0]}" "${EXE}"; STATUS=$? + + if ((STATUS)); then + xcwarning "Command dsymutil failed with exit code ${STATUS}." + continue + fi + + # Import the dSYM bundle. There is a momentary delay between + # creating the bundle and having it indexed; explicitly + # importing guarantees the mds database is up-to-date when we + # ask it for information about UUIDs and paths. + mdimport "${SCRATCH_BUNDLE}"; STATUS=$? + + if ((STATUS)); then + xcwarning "Command mdimport failed with exit code ${STATUS}." + continue + fi + fi + + SEEN_ARCH=() SEEN_PATH=() + + for BUNDLE in "${BUNDLES[@]}"; do + typeset -a BNDL_UUIDS BNDL_PATHS # keeps ShellLint happy + + eval "BNDL_UUIDS=$(mdls -raw -name com_apple_xcode_dsym_uuids "${BUNDLE}" | mdls_to_bash)" + eval "BNDL_PATHS=$(mdls -raw -name com_apple_xcode_dsym_paths "${BUNDLE}" | mdls_to_bash)" + + # Neither of these SHOULD occur, but curious things happen out + # in the field. + if ((${#BNDL_UUIDS[@]} != ${#BNDL_PATHS[@]})); then + xcwarning "${BUNDLE}: Malformed dSYM bundle." + continue + elif ((${#BNDL_UUIDS[@]} == 0)); then + xcwarning "${BUNDLE}: No DWARF information." + continue + fi + + # If no executable was specified, then the UUIDS and ARCHS + # arrays are empty. Populate them with information from the + # bundle. + if [[ ! "${EXE}" ]]; then + # The final UUIDS setting will be the intersection of the + # discovered set and the originally specified UUIDS. This + # is to prevent uploading potentially private information. + SOUGHT_UUIDS=("${UUIDS[@]}") + + UUIDS=() ARCHS=() + for BNDL_PATH in "${BNDL_PATHS[@]}"; do + set_uuids_archs "${BUNDLE}/${BNDL_PATH}" + done + + if ((${#SOUGHT_UUIDS[@]})); then + for I in "${!UUIDS[@]}"; do + for UUID in "${SOUGHT_UUIDS[@]}"; do + if [[ "${UUIDS[$I]}" == "${UUID}" ]]; then + continue 2 + fi + done + + # This is not the DWARF you are looking for... + xcdebug "Rejecting ${UUIDS[$I]} (${ARCHS[$I]}) as candidate DWARF file." + unset "UUIDS[$I]" "ARCHS[$I]" + done + fi + + unset SOUGHT_UUIDS + fi + + for I in "${!BNDL_UUIDS[@]}"; do + # See comment on extract_symbols_and_upload for why the + # full path to the companion file is required. + + BNDL_UUID="${BNDL_UUIDS[$I]}" DWARF_COMPANION="${BUNDLE}/${BNDL_PATHS[$I]}" + + for J in "${!ARCHS[@]}"; do + # A dSYM bundle can contain multiple architectures for + # multiple applications. Make sure we get the right + # one. + if [[ "${BNDL_UUID}" == "${UUIDS[$J]}" ]]; then + ARCH="${ARCHS[$J]}" + break + fi + done + + if [[ ! "${ARCH}" ]]; then + # This is not an error: it is legal for a dSYM bundle + # to contain debugging information for multiple + # executables (such as a framework with multiple + # subframeworks). Just ignore it. + xcdebug "No matching information found in ${DWARF_COMPANION} with UUID ${BNDL_UUID}." + continue + fi + + xcdebug "Found ${UUID} for ${ARCH} in ${DWARF_COMPANION}" + + # Have we already uploaded this file? + for J in "${!SEEN_ARCH[@]}"; do + if [[ "${ARCH}" == "${SEEN_ARCH[$J]}" ]] && cmp -s "${DWARF_COMPANION}" "${SEEN_PATH[$J]}"; then + xcdebug "${DWARF_COMPANION}: copy of ${SEEN_PATH[$J]}; no need to upload." + continue 2 + fi + done + + if [[ -f "${DWARF_COMPANION}" ]]; then + extract_symbols_and_upload "${DWARF_COMPANION}" "${ARCH}" "${EXE}" || exit $? + SEEN_ARCH+=("${ARCH}") SEEN_PATH+=("${DWARF_COMPANION}") + fi + done + done +done + +# For debugging odd cases. +if "${KEEP_TEMPORARIES}"; then + FCR_TEMPORARY_FILES=() +fi + +echo "Done." diff --git a/StoneIsland/plugins/cordova-plugin-firebase/src/ios/Firebase/Crash/dump_syms b/StoneIsland/plugins/cordova-plugin-firebase/src/ios/Firebase/Crash/dump_syms Binary files differnew file mode 100755 index 00000000..8d0ef781 --- /dev/null +++ b/StoneIsland/plugins/cordova-plugin-firebase/src/ios/Firebase/Crash/dump_syms diff --git a/StoneIsland/plugins/cordova-plugin-firebase/src/ios/Firebase/Crash/extract-keys b/StoneIsland/plugins/cordova-plugin-firebase/src/ios/Firebase/Crash/extract-keys new file mode 100755 index 00000000..0da57003 --- /dev/null +++ b/StoneIsland/plugins/cordova-plugin-firebase/src/ios/Firebase/Crash/extract-keys @@ -0,0 +1,12 @@ +#!/bin/bash + +PLIST="${HOME}/Library/Preferences/com.google.SymbolUpload.plist" + +[[ -f $PLIST ]] || exit + +defaults read com.google.SymbolUpload | +perl -nle '/"(app_\d+_\d+_ios_.*)"/ and print $1' | +while read KEY; do + APP_ID="${KEY#app_}"; APP_ID="${APP_ID//_/:}" + plutil -extract "${KEY}" json -o "${APP_ID}.json" "${PLIST}" +done diff --git a/StoneIsland/plugins/cordova-plugin-firebase/src/ios/Firebase/Crash/upload-sym b/StoneIsland/plugins/cordova-plugin-firebase/src/ios/Firebase/Crash/upload-sym new file mode 100755 index 00000000..1f8327dc --- /dev/null +++ b/StoneIsland/plugins/cordova-plugin-firebase/src/ios/Firebase/Crash/upload-sym @@ -0,0 +1,273 @@ +#!/bin/bash + +usage () { + echo >&2 "usage: $0 [-h] [-v] [-w|-e] service-account-file" +} + +help () { + usage + + cat >&2 <<EOF + + -h This message. + -v Increase verbosity. Multiple -v options will provide + increasing details. Use at least '-vv' when reporting bugs. + -w Treat errors as warnings. Does not change the exit status. + -e Treat warnings as errors. Does not change the exit status. + +The service account private key file is downloaded from the Firebase +console. See + + https://firebase.google.com/docs/crash/ios#upload_symbol_files + +for details on retrieving this file. Older keys may still be in the +registry. Consider using extract-keys.pl to retrieve them. + +Execute this script in the final phase of your build. It will not +work outside of Xcode, and should warn you if you try. See the +batch-upload script included in this distribution to upload symbols +outside of an Xcode build. + +Here is an example Run Script Phase you can add to your project +to invoke this script: + + "\${PODS_ROOT}/FirebaseCrashReporting/upload-sym" \\ + "\${HOME}/Library/Developer/My Project-1fad0d0767b42e.json" + +To avoid stopping the build should the upload fail, + + "\${PODS_ROOT}/FirebaseCrashReporting/upload-sym" -w \\ + "\${HOME}/Library/Developer/My Project-1fad0d0767b42e.json" + exit 0 # claim success no matter what + +EOF +} + +# Parse optional command-line flags. + +VERBOSE=0 WARNINGS_ONLY=0 ERRORS_ONLY=0 + +while getopts ehvw OPT; do + case "${OPT}" in + h) help; exit 0;; + v) VERBOSE=$((VERBOSE + 1));; + w) WARNINGS_ONLY=1;; + e) ERRORS_ONLY=1;; + ?) usage; exit 2;; + esac +done + +shift $((OPTIND - 1)) + +if ((WARNINGS_ONLY && ERRORS_ONLY)); then + echo >&2 "Either -w or -e may be specified, but not both." + echo >&2 + usage + exit 2 +fi + +SERVICE_ACCOUNT_FILE="$1"; shift + +if (($#)); then + echo >&2 "Unexpected argument '$1'" + echo >&2 + usage + exit 2 +fi + +export PATH=/bin:/usr/bin # play it safe + +# Load common utility routines. + +. "$(dirname "$0")/upload-sym-util.bash" + +# Make the error output Xcode-friendly. + +# This is a bit of Bash voodoo that cries for an explanation and is +# horribly underdocumented on-line. The construct '>(...)' starts a +# subprocess with its stdin connected to a pipe. After starting the +# subprocess, the parser replaces the construct with the NAME of the +# writable end of the pipe as a named file descriptor '/dev/fd/XX', +# then reevaluates the line. So, after the subprocess is started +# (which filters stdin and outputs to stderr [not stdout]), the line +# "exec 2> /dev/fd/XX" is evaluated. This redirects the main +# process's stderr to the given file descriptor. +# +# The end result is that anything sent to stderr of the form: +# file.in: line 47: blah blah +# is replaced with +# file.in:47: error: blah blah +# which Xcode will detect and emphasize in the formatted output. + +exec 2> >(sed -e 's/: line \([0-9]*\):/:\1: error:/' >&2) + +# Be long-winded about problems. The user may not understand how this +# script works or what prerequisites it has. If the user sees this, +# it is likely that they are executing the script outside of an Xcode +# build. + +ERRMSG=$'Value missing\n\nThis script must be executed as part of an Xcode build stage to have the\nproper environment variables set.' + +# Locate Xcode-generated files. + +: "${TARGET_BUILD_DIR:?"${ERRMSG}"}" +: "${FULL_PRODUCT_NAME:?"${ERRMSG}"}" + +DSYM_BUNDLE="${DWARF_DSYM_FOLDER_PATH?"${ERRMSG}"}/${DWARF_DSYM_FILE_NAME?"${ERRMSG}"}" +[[ -e "${DSYM_BUNDLE}" ]] || unset DSYM_BUNDLE + +EXECUTABLE="${TARGET_BUILD_DIR?"${ERRMSG}"}/${EXECUTABLE_PATH?"${ERRMSG}"}" + +# Locate dump_syms utility. + +if ! [[ -f "${FCR_DUMP_SYMS:=$(script_dir)/dump_syms}" && -x "${FCR_DUMP_SYMS}" ]]; then + xcerror "Cannot find dump_syms." + xcnote "It should have been installed with the Cocoapod. The location of dump_syms can be explicitly set using the environment variable FCR_DUMP_SYMS if you are using a non-standard install." + + exit 2 +fi + +if [[ ! "${FIREBASE_API_KEY}" || ! "${FIREBASE_APP_ID}" ]]; then + : "${SERVICE_PLIST:="$(find "${TARGET_BUILD_DIR}/${FULL_PRODUCT_NAME}" -name GoogleService-Info.plist | head -n1)"}" + : "${SERVICE_PLIST:?"GoogleService-Info.plist could not be located"}" + : "${FIREBASE_API_KEY:="$(property API_KEY "${SERVICE_PLIST}")"}" + : "${FIREBASE_APP_ID:="$(property GOOGLE_APP_ID "${SERVICE_PLIST}")"}" +fi + +if ! [[ "${FIREBASE_API_KEY}" ]]; then + xcerror "Unable to get API_KEY from ${SERVICE_PLIST}." + xcnote "Specify FIREBASE_API_KEY in environment." + exit 2 +fi + +if ! [[ "${FIREBASE_APP_ID}" ]]; then + xcerror "Unable to get GOOGLE_APP_ID from ${SERVICE_PLIST}." + xcnote "Specify FIREBASE_APP_ID in environment." + exit 2 +fi + +# Load Info.plist values (Bundle ID & version) + +INFOPLIST="${TARGET_BUILD_DIR}/${INFOPLIST_PATH}" + +if [[ -f "${INFOPLIST}" ]]; then + : "${FCR_PROD_VERS:="$(property CFBundleShortVersionString "${INFOPLIST}")"}" + : "${FCR_BUNDLE_ID:="$(property CFBundleIdentifier "${INFOPLIST}")"}" +fi + +if ! [[ "${FCR_PROD_VERS}" ]]; then + xcerror "Unable to get CFBundleShortVersionString from Info.plist." + xcnote "Specify FCR_PROD_VERS in environment." + exit 2 +fi + +if ! [[ "${FCR_BUNDLE_ID}" ]]; then + xcerror "Unable to get CFBundleIdentifier from Info.plist." + xcnote "Specify FCR_BUNDLE_ID in environment." + exit 2 +fi + +# Support legacy account file cache before giving up + +if [[ ! -f "${SERVICE_ACCOUNT_FILE}" ]]; then + xcwarning "Unable to find service account JSON file: ${SERVICE_ACCOUNT_FILE}" + "Please ensure you've followed the steps at:" + "https://firebase.google.com/docs/crash/ios#upload_symbol_files" + + xcdebug "Trying to extract JSON file from cache." + + CACHE_PLIST="${HOME}/Library/Preferences/com.google.SymbolUpload.plist" + + if [[ -f "${CACHE_PLIST}" ]]; then + fcr_mktemp SERVICE_ACCOUNT_FILE + /usr/bin/plutil -extract "app_${FIREBASE_APP_ID//:/_}" \ + json -o "${SERVICE_ACCOUNT_FILE}" "${CACHE_PLIST}" >/dev/null 2>&1 + if [[ ! -s "${SERVICE_ACCOUNT_FILE}" ]]; then + xcwarning "${FIREBASE_APP_ID} not found in cache." + /bin/rm -f "${SERVICE_ACCOUNT_FILE}" + else + xcnote "${FIREBASE_APP_ID} found in cache. Consider using extract-keys.pl to reduce reliance on cache." + fi + else + xcnote "No cache file found." + fi +fi + +if [[ ! -f "${SERVICE_ACCOUNT_FILE}" ]]; then + xcerror "All attempts to find the service account JSON file have failed." + xcnote "You must supply it on the command line." + echo >&2 -n "$0:1: note: "; usage + exit 2 +fi + +# Dump collected information if requested + +if ((VERBOSE >= 2)); then + xcnote "FIREBASE_API_KEY = ${FIREBASE_API_KEY}" + xcnote "FIREBASE_APP_ID = ${FIREBASE_APP_ID}" + xcnote "DSYM_BUNDLE = ${DSYM_BUNDLE:-(unset, will use symbols in executable)}" + xcnote "EXECUTABLE = ${EXECUTABLE}" + xcnote "INFOPLIST = ${INFOPLIST}" + xcnote "FCR_PROD_VERS = ${FCR_PROD_VERS}" + xcnote "FCR_BUNDLE_ID = ${FCR_BUNDLE_ID}" +fi + +# Create and upload symbol files for each architecture +if [[ -x "${SWIFT_DEMANGLE:=$(xcrun --find swift-demangle 2>/dev/null)}" ]]; then + SWIFT_DEMANGLE_COMMAND="${SWIFT_DEMANGLE} -simplified" +else + SWIFT_DEMANGLE_COMMAND=/bin/cat +fi + +for ARCH in ${ARCHS?:}; do + SYMBOL_FILE="SYMBOL_FILE_${ARCH}" + fcr_mktemp "${SYMBOL_FILE}" SCRATCH + + # Just because there is a dSYM bundle at that path does not mean + # it is the RIGHT dSYM bundle... + + if [[ -d "${DSYM_BUNDLE}" ]]; then + DSYM_UUID="$(dwarfdump --arch "${ARCH}" --uuid "${DSYM_BUNDLE}" | awk '{print $2}')" + EXE_UUID="$(dwarfdump --arch "${ARCH}" --uuid "${EXECUTABLE}" | awk '{print $2}')" + if ((VERBOSE > 1)); then + xcnote "dSYM bundle UUID: ${DSYM_UUID}" + xcnote "Executable UUID: ${EXE_UUID}" + fi + if [[ "${DSYM_UUID}" != "${EXE_UUID}" ]]; then + xcdebug "Current dSYM bundle is not valid." + unset DSYM_BUNDLE + fi + fi + + if [[ ! -d "${DSYM_BUNDLE}" ]]; then + xcdebug "Extracting dSYM from executable." + fcr_mktempdir TMP_DSYM + DSYM_BUNDLE="${TMP_DSYM}/${EXECUTABLE##*/}.dSYM" + xcrun dsymutil -o "${DSYM_BUNDLE}" "${EXECUTABLE}" + STATUS=$? + if ((STATUS)); then + xcerror "Command dsymutil failed with exit code ${STATUS}." + exit ${STATUS} + fi + fi + + "${FCR_DUMP_SYMS}" -a "${ARCH}" -g "${DSYM_BUNDLE}" "${EXECUTABLE}" >"${SCRATCH}" 2> >(sed -e 's/^/warning: dump_syms: /' | grep -v 'failed to demangle' >&2) + + STATUS=$? + if ((STATUS)); then + xcerror "Command dump_syms failed with exit code ${STATUS}." + exit ${STATUS} + fi + + ${SWIFT_DEMANGLE_COMMAND} <"${SCRATCH}" >|"${!SYMBOL_FILE}" || exit 1 + + if ((VERBOSE >= 2)); then + xcnote "${EXECUTABLE##*/} (architecture ${ARCH}) symbol dump follows (first 20 lines):" + head >&2 -n20 "${!SYMBOL_FILE}" + elif ((VERBOSE >= 1)); then + xcnote "${EXECUTABLE##*/} (architecture ${ARCH}) symbol dump follows (first line only):" + head >&2 -n1 "${!SYMBOL_FILE}" + fi + + fcr_upload_files "${!SYMBOL_FILE}" || exit 1 +done diff --git a/StoneIsland/plugins/cordova-plugin-firebase/src/ios/Firebase/Crash/upload-sym-util.bash b/StoneIsland/plugins/cordova-plugin-firebase/src/ios/Firebase/Crash/upload-sym-util.bash new file mode 100644 index 00000000..a8f8c655 --- /dev/null +++ b/StoneIsland/plugins/cordova-plugin-firebase/src/ios/Firebase/Crash/upload-sym-util.bash @@ -0,0 +1,382 @@ +# Output a clickable message. This will not count as a warning or +# error. + +xcnote () { + echo >&2 "${BASH_SOURCE[1]}:${BASH_LINENO[0]}: note: $*" +} + +# Output a clickable message prefixed with a warning symbol (U+26A0) +# and highlighted yellow. This will increase the overall warning +# count. A non-zero value for the variable ERRORS_ONLY will force +# warnings to be treated as errors. + +if ((ERRORS_ONLY)); then + xcwarning () { + echo >&2 "${BASH_SOURCE[1]}:${BASH_LINENO[0]}: error: $*" + } +else + xcwarning () { + echo >&2 "${BASH_SOURCE[1]}:${BASH_LINENO[0]}: warning: $*" + } +fi + +# Output a clickable message prefixed with a halt symbol (U+1F6D1) and +# highlighted red. This will increase the overall error count. Xcode +# will flag the build as failed if the error count is non-zero at the +# end of the build, even if this script returns a successful exit +# code. Set WARNINGS_ONLY to non-zero to prevent this. + +if ((WARNINGS_ONLY)); then + xcerror () { + echo >&2 "${BASH_SOURCE[1]}:${BASH_LINENO[0]}: warning: $*" + } +else + xcerror () { + echo >&2 "${BASH_SOURCE[1]}:${BASH_LINENO[0]}: error: $*" + } +fi + +xcdebug () { + if ((VERBOSE)); then + echo >&2 "${BASH_SOURCE[1]}:${BASH_LINENO[0]}: note: $*" + fi +} + +# Locate the script directory. + +script_dir () { + local SCRIPT="$0" SCRIPT_DIR="$(dirname "$0")" + + while SCRIPT="$(readlink "${SCRIPT}")"; do + [[ "${SCRIPT}" != /* ]] && SCRIPT="${SCRIPT_DIR}/${SCRIPT}" + SCRIPT_DIR="$(dirname "${SCRIPT}")" + done + + ( cd "${SCRIPT_DIR}"; pwd -P ) +} + +# Timestamp needed for various operations. Does not need to be exact, +# but does need to be consistent across web service calls. + +readonly NOW="$(/bin/date +%s)" + +# All files created by fcr_mktemp will be listed in FCR_TEMPORARY_FILES. +# Delete these when the enclosing script exits. (You may manually +# add files to this array as well to have them cleaned up on exit.) + +typeset -a FCR_TEMPORARY_FILES +trap 'STATUS=$?; rm -rf "${FCR_TEMPORARY_FILES[@]}"; exit ${STATUS}' 0 1 2 15 + +# Create a temporary file and add it to the list of files to delete when the +# script finishes. +# +# usage: fcr_mktemp VARNAME... + +fcr_mktemp () { + for VAR; do + eval "${VAR}=\$(mktemp -t com.google.FIRCrash) || return 1" + FCR_TEMPORARY_FILES+=("${!VAR}") + done +} + +# Create a temporary directory and add it to the list of files to +# delete when the script finishes. +# +# usage: fcr_mktempdir VARNAME... + +fcr_mktempdir () { + for VAR; do + eval "${VAR}=\$(mktemp -d -t com.google.FIRCrash) || return 1" + FCR_TEMPORARY_FILES+=("${!VAR}") + done +} + +# The keys we care about in the JSON objects. There are others that +# we do not use. Note that 'expires_at' and 'app_id' are not part of +# the original payload, but are computed from the environment used to +# make the call. + +FCR_SVC_KEYS=(client_email private_key private_key_id token_uri type) +FCR_TOK_KEYS=(access_token expires_at token_type app_id) + +# Extract a value from the property list. +# +# usage: property *name* *file* + +property () { + [[ -f "$2" ]] || echo '{}' >|"$2" # keeps PlistBuddy quiet + /usr/libexec/PlistBuddy "$2" -c "Print :$1" 2>/dev/null +} + +# Retrieve the property from the service account property list. +# +# usage: svc_property *name* + +svc_property () { + property "$1" "${SVC_PLIST}" +} + +# Does the same as svc_property above but for the token cache +# property list. +# +# usage: tok_property *name* + +tok_property () { + property "$1" "${TOK_PLIST}" +} + +# Verify that the service account property list has values for the +# required keys. Does not check the values themselves. + +fcr_verify_svc_plist () { + for key in "${FCR_SVC_KEYS[@]}"; do + if ! svc_property "${key}" >/dev/null; then + xcdebug "${key} not found in ${SVC_PLIST}. Service account invalid." + return 1 + fi + done +} + +# Verify that the token cache property list has values for the +# required keys. If the token_type is incorrect, the expiration date +# has been passed, or the application id does not match, return +# failure. + +fcr_verify_tok_plist () { + for key in "${FCR_TOK_KEYS[@]}"; do + if ! tok_property "${key}" >/dev/null; then + xcdebug "${key} not found in ${TOK_PLIST}. Token invalid." + return 1 + fi + done + + if [[ "$(tok_property token_type)" != "Bearer" ]]; then + xcwarning "Invalid token type '$(tok_property token_type)'." + return 1 + fi + + if (($(tok_property expires_at) <= NOW)); then + xcdebug "Token well-formed but expired at $(date -jf %s "$(tok_property expires_at)")." + echo '{}' >|"${TOK_PLIST}" + return 1 + fi + + if [[ "$(tok_property app_id)" != "${FIREBASE_APP_ID}" ]]; then + xcdebug "Cached token is for a different application." + echo '{}' >|"${TOK_PLIST}" + return 1 + fi +} + +# Convert a JSON certificate file to a PList certificate file. +# +# usage: fcr_load_certificate VARNAME + +fcr_load_certificate () { + : "${SERVICE_ACCOUNT_FILE:?must be the path to the service account JSON file.}" + fcr_mktemp "$1" + + if ! /usr/bin/plutil -convert binary1 "${SERVICE_ACCOUNT_FILE}" -o "${!1}"; then + xcerror "Unable to read service account file ${SERVICE_ACCOUNT_FILE}." + return 2 + fi +} + +# BASE64URL uses a sligtly different character set than BASE64, and +# uses no padding characters. + +function base64url () { + /usr/bin/base64 | sed -e 's/=//g; s/+/-/g; s/\//_/g' +} + +# Assemble the JSON Web Token (RFC 1795) +# +# usage: fcr_create_jwt *client-email* *token-uri* + +fcr_create_jwt () { + local JWT_HEADER="$(base64url <<<'{"alg":"RS256","typ":"JWT"}')" + local JWT_CLAIM="$(base64url <<<'{'"\"iss\":\"${1:?}\",\"aud\":\"${2:?}\",\"exp\":\"$((NOW + 3600))\",\"iat\":\"${NOW}\",\"scope\":\"https://www.googleapis.com/auth/mobilecrashreporting\""'}')" + local JWT_BODY="${JWT_HEADER}.${JWT_CLAIM}" + local JWT_SIG="$(echo -n "${JWT_BODY}" | openssl dgst -sha256 -sign <(svc_property private_key) -binary | base64url)" + + echo "${JWT_BODY}.${JWT_SIG}" +} + +# Set the BEARER_TOKEN variable for authentication. +# +# usage: fcr_authenticate + +fcr_authenticate () { + : "${FIREBASE_APP_ID:?required to select authentication credentials}" + + local SVC_PLIST + + fcr_load_certificate SVC_PLIST || return 2 + + local TOK_PLIST="${HOME}/Library/Preferences/com.google.SymbolUploadToken.plist" + + if ((VERBOSE > 2)); then + CURLOPT='--trace-ascii /dev/fd/2' + elif ((VERBOSE > 1)); then + CURLOPT='--verbose' + else + CURLOPT='' + fi + + # If the token will expire in the next sixty seconds (or already + # has), reload it. + if ! fcr_verify_tok_plist; then + xcdebug "Token cannot be used. Requesting OAuth2 token using installed credentials." + + if ! fcr_verify_svc_plist; then + xcerror "Incorrect/incomplete service account file." + return 2 + else + xcdebug "Certificate information appears valid." + fi + + TOKEN_URI="$(svc_property token_uri)" + CLIENT_EMAIL="$(svc_property client_email)" + + # Assemble the JSON Web Token (RFC 1795) + local JWT="$(fcr_create_jwt "${CLIENT_EMAIL}" "${TOKEN_URI}")" + + fcr_mktemp TOKEN_JSON + + HTTP_STATUS="$(curl ${CURLOPT} -o "${TOKEN_JSON}" -s -d grant_type='urn:ietf:params:oauth:grant-type:jwt-bearer' -d assertion="${JWT}" -w '%{http_code}' "${TOKEN_URI}")" + + if [[ "${HTTP_STATUS}" == 403 ]]; then + xcerror "Invalid certificate. Unable to retrieve OAuth2 token." + return 2 + elif [[ "${HTTP_STATUS}" != 200 ]]; then + cat >&2 "${TOKEN_JSON}" + return 2 + fi + + # Store the token in the preferences directory for future use. + /usr/bin/plutil -convert binary1 "${TOKEN_JSON}" -o "${TOK_PLIST}" + + EXPIRES_IN="$(tok_property expires_in)" + EXPIRES_AT="$((EXPIRES_IN + NOW))" + + /usr/libexec/PlistBuddy \ + -c "Add :app_id string \"${FIREBASE_APP_ID}\"" \ + -c "Add :expires_at integer ${EXPIRES_AT}" \ + -c "Add :expiration_date date $(TZ=GMT date -jf %s ${EXPIRES_AT})" \ + "${TOK_PLIST}" + + if ! fcr_verify_tok_plist; then + ((VERBOSE)) && /usr/libexec/PlistBuddy -c 'Print' "${TOK_PLIST}" + + echo '{}' >|"${TOK_PLIST}" + xcwarning "Token returned is not valid." + xcnote "If this error persists, download a fresh certificate." + + return 2 + fi + else + xcdebug "Token still valid." + EXPIRES_AT="$(tok_property expires_at)" + fi + + xcdebug "Token will expire on $(date -jf %s "${EXPIRES_AT}")." + xcdebug "Using service account with key $(svc_property private_key_id)." + + BEARER_TOKEN="$(tok_property access_token)" + + if [[ ! "${BEARER_TOKEN}" ]]; then + if ((VERBOSE)); then + xcwarning "Current malformed token cache:" + tok_property | while read; do xcnote "${REPLY}"; done + fi + xcerror "Unable to retrieve authentication token from server." + return 2 + fi + + return 0 +} + +# Upload the files to the server. +# +# Arguments: Names of files to upload. + +fcr_upload_files() { + fcr_authenticate || return $? + + : "${FCR_PROD_VERS:?}" + : "${FCR_BUNDLE_ID:?}" + : "${FIREBASE_APP_ID:?}" + : "${FIREBASE_API_KEY:?}" + : "${FCR_BASE_URL:=https://mobilecrashreporting.googleapis.com}" + + fcr_mktemp FILE_UPLOAD_LOCATION_PLIST META_UPLOAD_RESULT_PLIST + + if ((VERBOSE > 2)); then + CURLOPT='--trace-ascii /dev/fd/2' + elif ((VERBOSE > 1)); then + CURLOPT='--verbose' + else + CURLOPT='' + fi + + for FILE; do + xcdebug "Get signed URL for uploading." + + URL="${FCR_BASE_URL}/v1/apps/${FIREBASE_APP_ID}" + + HTTP_STATUS="$(curl ${CURLOPT} -o "${FILE_UPLOAD_LOCATION_PLIST}" -sL -H "X-Ios-Bundle-Identifier: ${FCR_BUNDLE_ID}" -H "Authorization: Bearer ${BEARER_TOKEN}" -X POST -d '' -w '%{http_code}' "${URL}/symbolFileUploadLocation?key=${FIREBASE_API_KEY}")" + STATUS=$? + + if [[ "${STATUS}" == 22 && "${HTTP_STATUS}" == 403 ]]; then + xcerror "Unable to access resource. Token invalid." + xcnote "Please verify the service account file." + return 2 + elif [[ "${STATUS}" != 0 ]]; then + xcerror "curl exited with non-zero status ${STATUS}." + ((STATUS == 22)) && xcerror "HTTP response code is ${HTTP_STATUS}." + return 2 + fi + + /usr/bin/plutil -convert binary1 "${FILE_UPLOAD_LOCATION_PLIST}" || return 1 + + UPLOAD_KEY="$(property uploadKey "${FILE_UPLOAD_LOCATION_PLIST}")" + UPLOAD_URL="$(property uploadUrl "${FILE_UPLOAD_LOCATION_PLIST}")" + ERRMSG="$(property error:message "${FILE_UPLOAD_LOCATION_PLIST}")" + + if [[ "${ERRMSG}" ]]; then + if ((VERBOSE)); then + xcnote "Server response:" + /usr/bin/plutil -p "${FILE_UPLOAD_LOCATION_PLIST}" >&2 + fi + xcerror "symbolFileUploadLocation: ${ERRMSG}" + xcnote "symbolFileUploadLocation: Failed to get upload location." + return 1 + fi + + xcdebug "Upload symbol file." + + HTTP_STATUS=$(curl ${CURLOPT} -sfL -H 'Content-Type: text/plain' -H "Authorization: Bearer ${BEARER_TOKEN}" -w '%{http_code}' -T "${FILE}" "${UPLOAD_URL}") + STATUS=$? + + if ((STATUS == 22)); then # exit code 22 is a non-successful HTTP response + xcerror "upload: Unable to upload symbol file (HTTP Status ${HTTP_STATUS})." + return 1 + elif ((STATUS != 0)); then + xcerror "upload: Unable to upload symbol file (reason unknown)." + return 1 + fi + + xcdebug "Upload metadata information." + + curl ${CURLOPT} -sL -H 'Content-Type: application/json' -H "X-Ios-Bundle-Identifier: ${FCR_BUNDLE_ID}" -H "Authorization: Bearer ${BEARER_TOKEN}" -X POST -d '{"upload_key":"'"${UPLOAD_KEY}"'","symbol_file_mapping":{"symbol_type":2,"app_version":"'"${FCR_PROD_VERS}"'"}}' "${URL}/symbolFileMappings:upsert?key=${FIREBASE_API_KEY}" >|"${META_UPLOAD_RESULT_PLIST}" || return 1 + /usr/bin/plutil -convert binary1 "${META_UPLOAD_RESULT_PLIST}" || return 1 + + ERRMSG="$(property error:message "${META_UPLOAD_RESULT_PLIST}")" + + if [[ "${ERRMSG}" ]]; then + xcerror "symbolFileMappings:upsert: ${ERRMSG}" + xcnote "symbolFileMappings:upsert: The metadata for the symbol file failed to update." + return 1 + fi + done +} diff --git a/StoneIsland/plugins/cordova-plugin-firebase/src/ios/Firebase/Crash/upload-sym.sh b/StoneIsland/plugins/cordova-plugin-firebase/src/ios/Firebase/Crash/upload-sym.sh new file mode 100755 index 00000000..c0a34e38 --- /dev/null +++ b/StoneIsland/plugins/cordova-plugin-firebase/src/ios/Firebase/Crash/upload-sym.sh @@ -0,0 +1,4 @@ +#!/bin/bash + +echo "$0:0: error: $0 has been removed. Please use upload-sym instead." +exit 1 |
