+magicParseLabel() {
+ # Desc: Parses -l option to set label
+ # In : optionLabel, argLabel
+ # Out: vars: label
+ # Depends: Bash 5.0.3, vbm(), yell()
+ local fn
+
+ # Save function name
+ fn="${FUNCNAME[0]}";
+
+ vbm "STATUS:$fn:Started magicParseLabel() function.";
+ # Do nothing if optionLabel not set to true.
+ if [[ ! "$optionLabel" = "true" ]]; then
+ vbm "STATUS:$fn:optionlabel not set to 'true'. Returning early.";
+ return;
+ fi;
+ # Set label if optionLabel is true
+ if [[ "$optionLabel" = "true" ]]; then
+ label="_""$argLabel";
+ vbm "STATUS:$fn:Set label:$label";
+ fi;
+ vbm "STATUS:$fn:Finished magicParseLabel() function.";
+} # Set label used in output file name
+magicParseProcessStrings() {
+ # Desc: Processes user-supplied process strings into process commands for appendFileTar().
+ # Usage: magicParseProcessStrings
+ # In : vars: optionProcString optionNoStoreRaw optionStoreRaw argRawFileExt
+ # arry: argProcStrings, argProcFileExts
+ # Out: arry: procStrings, procFileExts
+ # Depends Bash 5.0.3, yell(), vbm()
+ local fn rawFileExt
+
+ # Save function name
+ fn="${FUNCNAME[0]}";
+
+ vbm "STATUS:$fn:Starting magicParseProcessStrings() function.";
+ vbm "STATUS:$fn:var:optionProcString:$optionProcString";
+ vbm "STATUS:$fn:var:optionNoStoreRaw:$optionNoStoreRaw";
+ vbm "STATUS:$fn:var:optionStoreRaw:$optionStoreRaw";
+ vbm "STATUS:$fn:var:argRawFileExt:$argRawFileExt";
+ vbm "STATUS:$fn:ary:argProcStrings:${argProcStrings[*]}";
+ vbm "STATUS:$fn:ary:argProcFileExts:${argProcFileExts[*]}"
+ # Validate input
+ ## Validate argRawFileExt
+ if [[ "$argRawFileExt" =~ ^[.][[:alnum:]]*$ ]]; then
+ rawFileExt="$argRawFileExt" && \
+ vbm "DEBUG :$fn:Set rawFileExt to \"$argRawFileExt\"";
+ else
+ vbm "DEBUG :$fn:Validation failure for $argRawFileExt . Not set to rawFileExt.";
+ fi;
+
+ # Add default stdin output file entries for procStrings, procFileExts
+ ## Check if user specified that no raw stdin be saved.
+ if [[ ! "$optionNoStoreRaw" = "true" ]]; then
+ ### T: --no-store-raw not set. Store raw. Append procStrings with cat.
+ vbm "DEBUG :$fn:--no-store-raw not set. Storing raw.";
+ #### Append procStrings array
+ procStrings+=("cat ") && \
+ vbm "DEBUG :$fn:Appended \"cat \" to procStrings";
+ vbm "DEBUG :$fn:procStrings array:${procStrings[*]}";
+ #### Check if --store-raw set.
+ if [[ "$optionStoreRaw" = "true" ]]; then
+ ##### T: --store-raw set. Append procFileExts with user-specified file ext
+ vbm "DEBUG :$fn:--store-raw set.";
+ procFileExts+=("$rawFileExt") && \
+ vbm "DEBUG :$fn:Appended $rawFileExt to procFileExts";
+ vbm "STATUS:$fn:procFileExts array:${procFileExts[*]}";
+ else
+ ##### F: --store-raw not set. Append procFileExts with default ".stdin" file ext
+ ###### Append procFileExts array
+ procFileExts+=(".stdin") && \
+ vbm "DEBUG :$fn:Appended \".stdin\" to procFileExts";
+ vbm "STATUS:$fn:procFileExts array:${procFileExts[*]}";
+ fi;
+ else
+ ### F: --no-store-raw set. Do not store raw.
+ #### Do not append procStrings or procFileExts arrays.
+ vbm "STATUS:$fn:--no-store-raw set. Not storing raw.";
+ vbm "STATUS:$fn:procFileExts array:${procFileExts[*]}";
+ fi;
+
+ # Do nothing more if optionProcString not set to true.
+ if [[ ! "$optionProcString" = "true" ]]; then
+ vbm "STATUS:$fn:optionProcString not set to 'true'. Returning early.";
+ return; fi;
+ # Validate input array indices
+ ## Make sure that argProcStrings and argProcFileExts have same index counts
+ if ! [[ "${#argProcStrings[@]}" -eq "${#argProcFileExts[@]}" ]]; then
+ yell "ERROR:$fn:Mismatch in number of elements in arrays argProcStrings and argProcFileExts:${#argProcStrings[@]} DNE ${#argProcFileExts[@]}";
+ yell "STATUS:$fn:argProcStrings:${argProcStrings[*]}"; yell "STATUS:$fn:argProcFileExts:${argProcFileExts[*]}"; exit 1; fi;
+ ## Make sure that no array elements are blank
+ for element in "${argProcStrings[@]}"; do
+ if [[ -z "$element" ]]; then yell "ERROR:$fn:Empty process string specified. Exiting."; exit 1; fi; done
+ for element in "${argProcFileExts[@]}"; do
+ if [[ -z "$element" ]]; then yell "ERROR:$fn:Empty output file extension specified. Exiting."; exit 1; fi; done
+ ## Make sure that no process string starts with '-' (ex: if only one arg supplied after '-p' option)
+ for element in "${argProcStrings[@]}"; do
+ if [[ "$element" =~ ^[-][[:print:]]*$ ]] && [[ ! "$element" =~ ^[[:print:]]*$ ]]; then
+ yell "ERROR:$fn:Illegal character '-' at start of process string element:\"$element\"";
+ exit 1; fi; done;
+ vbm "STATUS:$fn:Quick check shows argProcStrings and argProcFileExts appear to have valid contents.";
+ vbm "STATUS:$fn:argProcStrings:${argProcStrings[*]}"
+ vbm "STATUS:$fn:argProcStrings:${argProcFileExts[*]}"
+ procStrings+=("${argProcStrings[@]}"); # Export process command strings
+ procFileExts+=("${argProcFileExts[@]}"); # Export process command strings
+ vbm "STATUS:$fn:Finished magicParseProcessStrings() function.";
+} # Validate and save process strings and file extensions to arrays procStrings, procFileExts
+magicParseRecipients() {
+ # Desc: Parses recipient arguments specified by '-r' or '-R' options
+ # Usage: magicParseRecipients
+ # In : vars: optionEncrypt, optionRecArg, optionRecDir
+ # arry: argRecPubKeys (-r), argRecDir (-R)
+ # Out: vars: cmd_encrypt, cmd_encrypt_suffix
+ # Depends: head 8.30, checkapp(), checkAgePubkey(), validateInput()
+ local fn recipients recipientDir recFileLine updateRecipients
+ local -a recPubKeysValid candRecPubKeysValid
+
+ # Save function name
+ fn="${FUNCNAME[0]}";
+ vbm "STATUS:$fn:Starting magicParseRecipients() function.";
+
+ # Catch illegal option combinations
+ ## Catch case if '-e' is set but neither '-r' nor '-R' is set
+ if [[ "$optionEncrypt" = "true" ]] && \
+ ! { [[ "$optionRecArg" = "true" ]] || [[ "$optionRecDir" = "true" ]]; }; then
+ yell "ERROR:$fn:\\'-e\\' set but no \\'-r\\' or \\'-R\\' set."; exit 1; fi;
+ ## Catch case if '-r' or '-R' set but '-e' is not
+ if [[ ! "$optionEncrypt" = "true" ]] && \
+ { [[ "$optionRecArg" = "true" ]] || [[ "$optionRecDir" = "true" ]]; }; then
+ yell "ERROR:$fn:\\'-r\\' or \\'-R\\' set but \\'-e\\' is not set."; exit 1; fi;
+
+ # Handle no encryption cases
+ if [[ ! "$optionEncrypt" = "true" ]]; then
+ cmd_encrypt="cat " && vbm "STATUS:$fn:cmd_encrypt:$cmd_encrypt";
+ cmd_encrypt_suffix="" && vbm "STATUS:$fn:cmd_encrypt_suffix:$cmd_encrypt_suffix";
+ vbm "DEBUG :$fn:Encryption not enabled.";
+ return; fi;
+
+ # Handle encryption cases
+ ## Check age availability
+ if ! checkapp age; then yell "ERROR:$fn:age not available. Exiting."; exit 1; fi
+ ## Parse '-r' options: validate and append pubkeys from argRecPubKeys to recPubKeysValid
+ if [[ "$optionRecArg" = "true" ]]; then
+ for pubkey in "${argRecPubKeys[@]}"; do # Validate recipient pubkey strings by forming test message
+ vbm "DEBUG :$fn:Testing pubkey string:$pubkey";
+ if checkAgePubkey "$pubkey" && \
+ ( validateInput "$pubkey" "ssh_pubkey" || validateInput "$pubkey" "age_pubkey"); then
+ #### Add validated pubkey to recPubKeysValid array
+ recPubKeysValid+=("$pubkey") && \
+ vbm "DEBUG :$fn:recPubkeysValid:pubkey added:$pubkey";
+ else
+ yell "ERROR:$fn:Exit code ""$?"". Invalid recipient pubkey string. Exiting."; exit 1;
+ fi;
+ done;
+ vbm "STATUS:$fn:Finished processing argRecPubKeys array";
+ vbm "DEBUG :$fn:Array of validated pubkeys:${recPubKeysValid[*]}";
+ fi;
+ ## Parse '-R' options: validate and append pubkeys in argRecDir to recPubKeysValid
+ if [[ "$optionRecDir" = "true" ]]; then
+ ### Check that argRecDir is a directory
+ if [[ -d "$argRecDir" ]]; then
+ recipientDir="$argRecDir" && \
+ vbm "STATUS:$fn:Recipient watch directory detected:\"$recipientDir\"";
+ #### Initialize variable indicating outcome of pubkey review
+ unset updateRecipients
+ #### Add existing recipients from '-r' option
+ candRecPubKeysValid=("${recPubKeysValid[@]}");
+ #### Parse files in recipientDir
+ for file in "$recipientDir"/*; do
+ ##### Read first line of each file
+ recFileLine="$(head -n1 "$file")" && \
+ vbm "STATUS:$fn:Checking if pubkey:\"$recFileLine\"";
+ ##### check if first line is a valid pubkey
+ if checkAgePubkey "$recFileLine" && \
+ ( validateInput "$recFileLine" "ssh_pubkey" || validateInput "$recFileLine" "age_pubkey"); then
+ ###### T: add candidate pubkey to candRecPubKeysValid
+ candRecPubKeysValid+=("$recFileLine") && \
+ vbm "STATUS:$fn:RecDir pubkey is valid pubkey:\"$recFileLine\"";
+ else
+ ###### F: throw warning;
+ yell "ERROR:$fn:Invalid recipient file detected. Not modifying recipient list:$recFileLine";
+ updateRecipients="false";
+ fi;
+ done
+ #### Write candRecPubKeysValid array to recPubKeysValid if no invalid key detected
+ if ! [[ "$updateRecipients" = "false" ]]; then
+ recPubKeysValid=("${candRecPubKeysValid[@]}") && \
+ vbm "STATUS:$fn:Wrote candRecPubkeysValid to recPubKeysValid:\"${recPubKeysValid[*]}\"";
+ fi;
+ fi;
+ fi;
+
+ ## Form age recipient string from recPubKeysValid
+ for pubkey in "${recPubKeysValid[@]}"; do
+ recipients="$recipients""-r '$pubkey' ";
+ vbm "STATUS:$fn:Added pubkey for forming age recipient string:""$pubkey";
+ vbm "DEBUG :$fn:recipients:""$recipients";
+ done;
+
+ ## Output cmd_encrypt, cmd_encrypt_suffix from recipients
+ cmd_encrypt="age ""$recipients " && vbm "STATUS:$fn:cmd_encrypt:$cmd_encrypt";
+ cmd_encrypt_suffix=".age" && vbm "STATUS:$fn:cmd_encrypt_suffix:$cmd_encrypt_suffix";
+
+ vbm "STATUS:$fn:Finished magicParseRecipients() function.";
+} # Sets cmd_encrypt, cmd_encrypt_suffix from -r, -R args