diff --git a/occ_scan_bad_signature.sh b/occ_scan_bad_signature.sh deleted file mode 100755 index b626dd5..0000000 --- a/occ_scan_bad_signature.sh +++ /dev/null @@ -1,887 +0,0 @@ -#!/usr/bin/env bash - -CUR_IFS=$IFS - -script_name="$(basename $(realpath $0))" -script_dir="$(dirname $(realpath $0))" - -conf_dir="${script_dir}/conf" -snippet_dir="${script_dir}/snippets" -report_dir="${script_dir}/reports" - -declare -a unsorted_website_arr -declare -a website_arr - -declare -a unsorted_account_arr -declare -a account_arr - -declare -a unsorted_selected_user_arr -declare -a selected_user_arr - -LOCK_DIR="/tmp/${script_name%%.*}.LOCK" -log_file="${LOCK_DIR}/${script_name%%.*}.log" - -run_date=$(date +%Y-%m-%d-%H%M) - - -# ============= -# --- Some functions -# ============= - -usage() { - - [[ -n "$1" ]] && error "$1" - - [[ $terminal ]] && echo -e " -\033[1mUsage:\033[m - - $(basename $0) -s - -\033[1mDescription\033[m - - Scans the encrypted files of one, several or all Nextcloud accounts - and reports every file that fails to decrypt (e.g. 'Bad Signature' - errors thrown by Server-Side Encryption). Every file is read once - and its content discarded - the script is READ-ONLY and changes, - moves or deletes nothing. - - You will be asked interactively which account(s) to scan: - - - a blank separated list of account names - - or 'all' to scan every existing account - -\033[1mOptions\033[m - - -s - The site of the nextcloud instance. - -\033[1mExample:\033[m - - Runs this script on system 'cloud-01.oopen.de' - - $(basename $0) -s cloud-01.oopen.de -" - - clean_up 1 - -} - - -clean_up() { - - # Perform program exit housekeeping - [[ -n "$scan_php_file" ]] && rm -f "$scan_php_file" 2> /dev/null - rm -rf "$LOCK_DIR" - blank_line - exit $1 -} - -is_number() { - - return $(test ! -z "${1##*[!0-9]*}" > /dev/null 2>&1); - - # - also possible - # - - #[[ ! -z "${1##*[!0-9]*}" ]] && return 0 || return 1 - #return $([[ ! -z "${1##*[!0-9]*}" ]]) -} - -echononl(){ - if $terminal ; then - echo X\\c > /tmp/shprompt$$ - if [ `wc -c /tmp/shprompt$$ | awk '{print $1}'` -eq 1 ]; then - echo -e -n "$*\\c" 1>&2 - else - echo -e -n "$*" 1>&2 - fi - rm /tmp/shprompt$$ - fi -} -echo_done() { - if $terminal ; then - echo -e "\033[75G[ \033[32mdone\033[m ]" - fi -} -echo_ok() { - if $terminal ; then - echo -e "\033[75G[ \033[32mok\033[m ]" - fi -} -echo_warning() { - if $terminal ; then - echo -e "\033[75G[ \033[33m\033[1mwarn\033[m ]" - fi -} -echo_failed(){ - if $terminal ; then - echo -e "\033[75G[ \033[1;31mfailed\033[m ]" - fi -} -echo_skipped() { - if $terminal ; then - echo -e "\033[75G[ \033[37mskipped\033[m ]" - fi -} -echo_funde() { - if $terminal ; then - echo -e "\033[75G[ \033[33m\033[1mFunde!\033[m ]" - fi -} - -fatal (){ - echo "" - echo "" - if $terminal ; then - echo -e " [ \033[31m\033[1mFatal\033[m ]: \033[37m\033[1m$*\033[m" - echo "" - echo -e " \033[31m\033[1mScript will be interrupted..\033[m!" - else - echo " [ Fatal ]: $*" - echo "" - echo " Script was terminated...." - fi - clean_up 1 -} - -error(){ - echo "" - if $terminal ; then - echo -e " [ \033[31m\033[1mError\033[m ]: $*" - else - echo " [ Error ]: $*" - fi - echo "" -} - -warn (){ - if $terminal ; then - echo "" - echo -e " [ \033[33m\033[1mWarning\033[m ]: $*" - echo "" - fi -} - -info (){ - if $terminal ; then - echo "" - echo -e " [ \033[32m\033[1mInfo\033[m ]: $*" - echo "" - fi -} - -# - Remove leading/trailling whitespaces -# - -trim() { - local var="$*" - var="${var#"${var%%[![:space:]]*}"}" # remove leading whitespace characters - var="${var%"${var##*[![:space:]]}"}" # remove trailing whitespace characters - echo -n "$var" -} - -## - Check if a given array (parameter 2) contains a given string (parameter 1) -## - -containsElement () { - local e - for e in "${@:2}"; do [[ "$e" == "$1" ]] && return 0; done - return 1 -} - -## - Percentage (1 decimal) of parameter 1 (part) against parameter 2 (total) -## - Returns "0.0" if total is empty, zero or non-numeric. -## - -calc_percent() { - local _part="$1" - local _total="$2" - if [[ -z "$_total" ]] || ! [[ "$_total" =~ ^[0-9]+$ ]] || [[ "$_total" -eq 0 ]] ; then - echo "0.0" - else - awk -v b="$_part" -v t="$_total" 'BEGIN { printf "%.1f", (b/t)*100 }' - fi -} - -blank_line() { - if $terminal ; then - echo "" - fi -} - - - -# - Running in a terminal? -# - -if [[ -t 1 ]] ; then - terminal=true -else - terminal=false -fi - -# ---------- -# - Jobhandling -# ---------- - -if pgrep -f "$(basename $0)" | grep -q -v $$ ; then - - msg="A previos instance of script \"`basename $0`\" seems already be running." - - echo "" - if $terminal ; then - echo -e "[ \033[31m\033[1mFatal\033[m ]: $msg" - echo "" - echo -e " \033[31m\033[1mScript was interupted\033[m!" - else - echo " [ Fatal ]: $msg" - echo "" - echo " Script was interupted!" - fi - echo - - exit 1 -else - if [[ -d "$LOCK_DIR" ]] ; then - rm -rf "$LOCK_DIR" 2> /dev/null - fi -fi - - -# - If job already runs, stop execution.. -# - -if mkdir "$LOCK_DIR" 2> /dev/null ; then - - # - Remove lockdir when the script finishes, or when it receives a signal - # - - trap clean_up SIGHUP SIGINT SIGTERM - -else - - msg="A previos instance of script \"`basename $0`\" seems already be running." - - echo "" - if $terminal ; then - echo -e "[ \033[31m\033[1mFatal\033[m ]: $msg" - echo "" - echo -e " \033[31m\033[1mScript was interupted\033[m!" - else - echo " [ Fatal ]: $msg" - echo "" - echo " Script was interupted!" - fi - echo - - exit 1 - -fi - - -# ------------- -# - Read in Commandline arguments -# ------------- -while getopts hs: opt ; do - case $opt in - h) usage ;; - s) WEBSITE=$OPTARG ;; - \?) usage - esac -done - -if [[ -z "$WEBSITE" ]] ; then - - while IFS='' read -r -d '' _conf_file ; do - source $_conf_file - if [[ -n "$WEBSITE" ]] ; then - unsorted_website_arr+=("${WEBSITE}:$_conf_file") - fi - WEBSITE="" - done < <(find "${conf_dir}" -maxdepth 1 -type f -name "*.conf" -print0) - - # - Sort array - # - - IFS=$'\n' website_arr=($(sort <<<"${unsorted_website_arr[*]}")) - - # Which cloud instance (website) would you like to update - # - source ${snippet_dir}/get-cloud-instance-to-update.sh - -else - - while IFS='' read -r -d '' _conf_file ; do - if $(grep -E -q "WEBSITE=\"?${WEBSITE}\"?" ${_conf_file} 2> /dev/null) ; then - conf_file="${_conf_file}" - break - fi - done < <(find "${conf_dir}" -maxdepth 1 -type f -name "*.conf" -print0) - -fi - - -# - Reset IFS -# - -IFS=$CUR_IFS - -DEFAULT_SRC_BASE_DIR="/usr/local/src/nextcloud" -DEFAULT_HTTP_USER="www-data" -DEFAULT_HTTP_GROUP="www-data" -DEFAULT_PHP_ENGINE='FPM' - -blank_line -echononl " Include Configuration file '$(basename "${conf_file}")'.." -if [[ ! -f $conf_file ]]; then - echo_skipped - fatal "Missing configuration file '$conf_file'." -else - source $conf_file - echo_ok -fi - -DEFAULT_WEB_BASE_DIR="/var/www/${WEBSITE}" -[[ -n "$WEB_BASE_DIR" ]] || WEB_BASE_DIR=$DEFAULT_WEB_BASE_DIR - -if [[ ! -d ${WEB_BASE_DIR} ]] ; then - fatal "Web base directory '$WEB_BASE_DIR' not found!" -fi - -DATA_DIR="$(realpath ${WEB_BASE_DIR}/data)" - -[[ -n "$PHP_ENGINE" ]] || PHP_ENGINE=$DEFAULT_PHP_ENGINE - -INSTALL_DIR="$(realpath ${WEB_BASE_DIR}/nextcloud)" -CURRENT_VERSION="$(basename $INSTALL_DIR | cut -d"-" -f2)" - - -# ============= -# --- Some -# ============= - -# - Support systemd ? -# - -SYSTEMD_EXISTS=false -systemd=$(which systemd) -systemctl=$(which systemctl) - -if [[ -n "$systemd" ]] || [[ -n "$systemctl" ]] ; then - SYSTEMD_EXISTS=true -fi - -#clear - -if $terminal ; then - echo "" - echo -e "\033[32m-----\033[m" - echo -e "Scan encrypted files for \033[1mBad Signature\033[m errors on system \033[1m${WEB_BASE_DIR}\033[m" - echo -e "\033[1m - Read-only: every file is decrypted once and the content discarded, - reporting every file that fails Server-Side Encryption's signature - check. Nothing is changed, moved or deleted.\033[m" - echo -e "\033[32m-----\033[m" -fi - - -# ============= -# --- Some checks -# ============= - -DEFAULT_HTTP_USER="www-data" -DEFAULT_HTTP_GROUP="www-data" - - -NGINX_IS_ENABLED=false -APACHE2_IS_ENABLED=false - -# Get Webservice environment as IS_HTTPD_RUNNING, HTTP_USER, HTTP_GROUP.. -# -source ${snippet_dir}/get-webservice-environment.sh - - -# Check PHP Version -# -source ${snippet_dir}/get-php-major-version.sh - - -# Get full qualified PHP command -# -source ${snippet_dir}/get-path-of-php-command.sh - - -if [[ ! -x "$PHP_BIN" ]]; then - fatal "No PHP binary found!" -fi - - -# ============= -# --- Determine existing accounts -# ============= - -blank_line -echononl " Get list of current accounts.." - -mapfile -t unsorted_account_arr < <(su -c "${PHP_BIN} ${INSTALL_DIR}/occ user:list" -s /bin/bash $HTTP_USER 2> ${log_file} | awk -F'[:[:space:]]+' '{print $3}' 2>> ${log_file} ) - -if [[ $? -gt 0 ]] || [[ -s "${log_file}" ]] ; then - echo_failed - fatal "$(cat $log_file)" -else - echo_ok - > "$log_file" -fi - -# - Sort array -# - -IFS=$'\n' account_arr=($(sort <<<"${unsorted_account_arr[*]}")) -IFS=$CUR_IFS - - -# ============= -# --- Ask which account(s) to scan -# ============= - -echo "" -echo "" -echo -e "\033[32m-----\033[m" -echo "" -echo -e " Existing accounts on \033[1m${WEBSITE}\033[m\n" -echo -en "\033[33m" -printf " %s\n" "${account_arr[@]}" -echo -en "\033[m" -blank_line - -echo "" -echo "" -echo -e "\033[32m-----\033[m" -echo "" -echo -e " Which account(s) would you like to scan for 'Bad Signature' errors?" -echo "" -echo " - enter a list separated by spaces" -echo -e " - or type \033[33mall\033[m to scan every existing account" -echo "" -SELECTED_USERS= -while [[ -z "$(trim ${SELECTED_USERS})" ]] ; do - - echononl " Account(s) to scan: " - read SELECTED_USERS - - if [[ -z "$(trim ${SELECTED_USERS})" ]] ; then - echo -e "\n\t\033[33m\033[1mEntry must not be empty. Type \033[m\033[1mall\033[33m to scan every account.\033[m\n" - continue - fi - - if [[ "${SELECTED_USERS,,}" = "all" ]] ; then - selected_user_arr=("${account_arr[@]}") - break - fi - - IFS=' ' read -ra unsorted_selected_user_arr <<< "${SELECTED_USERS}" - - _all_valid=true - for _user in "${unsorted_selected_user_arr[@]}" ; do - if ! containsElement "${_user}" "${account_arr[@]}" ; then - echo -e "\n\t\033[33m\033[1m No account \033[m\033[1m${_user}\033[33m present!\033[m - Try again..\n" - SELECTED_USERS="" - _all_valid=false - break - fi - done - - $_all_valid || continue - - # - Sort array - # - - IFS=$'\n' selected_user_arr=($(sort <<<"${unsorted_selected_user_arr[*]}")) - IFS=$CUR_IFS - -done - - -# ============= -# --- Write out the (embedded) PHP scan script into the Nextcloud -# --- install directory - it needs to sit next to 'occ' since it -# --- bootstraps Nextcloud the same way occ does. -# ============= - -scan_php_file="${INSTALL_DIR}/.occ_scan_bad_signature_$$.php" - -cat > "$scan_php_file" <<'PHP_SCAN_EOF' - [--before=YYYY-MM-DD] [--after=YYYY-MM-DD] - * - * Ausgabe (TSV, nach STDOUT): - * user \t path \t size_bytes \t mtime \t error - * Eine Zeile pro Datei, bei der das Lesen fehlgeschlagen ist. - * Fortschritts-/Debug-/Zusammenfassungsmeldungen gehen nach STDERR. - */ - -error_reporting(E_ALL); -ini_set('display_errors', '1'); - -fwrite(STDERR, "DEBUG: Skript gestartet, PID=" . getmypid() . "\n"); - -// Faengt fatale, NICHT als Throwable auftretende Fehler ab (z.B. Memory -// Limit exhausted), die sonst komplett stumm bleiben wuerden. -register_shutdown_function(function () { - $err = error_get_last(); - if ($err !== null && in_array($err['type'], [E_ERROR, E_PARSE, E_CORE_ERROR, E_COMPILE_ERROR], true)) { - fwrite(STDERR, "DEBUG: FATAL bei Shutdown: [{$err['type']}] {$err['message']} in {$err['file']}:{$err['line']}\n"); - } else { - fwrite(STDERR, "DEBUG: Shutdown ohne erkannten Fatal-Error.\n"); - } -}); - -// WICHTIG: Muss VOR dem require von lib/base.php gesetzt werden. -// Ohne diese Konstante fuehrt lib/base.php am Ende automatisch -// OC::handleRequest() aus (als waere dies ein normaler HTTP-Request). -define('OC_CONSOLE', 1); - -$oldWorkingDir = getcwd(); -if ($oldWorkingDir === false) { - fwrite(STDERR, "Konnte aktuelles Arbeitsverzeichnis nicht ermitteln. Bitte mit absolutem Pfad aufrufen.\n"); - exit(1); -} -chdir(__DIR__); - -fwrite(STDERR, "DEBUG: vor require lib/base.php\n"); -require_once __DIR__ . '/lib/base.php'; -fwrite(STDERR, "DEBUG: nach require lib/base.php - Bootstrap abgeschlossen\n"); - -chdir($oldWorkingDir); - -if (function_exists('posix_getuid') && posix_getuid() === 0) { - fwrite(STDERR, "Bitte NICHT als root ausfuehren, sondern als Webserver-User, z.B.:\n"); - fwrite(STDERR, " sudo -u www-data php " . __FILE__ . "\n"); - exit(1); -} - -// Ab hier alles in einem Catch-All, damit ein Throwable garantiert HIER -// landet und nicht beim (auf STDOUT/STDERR ggf. still bleibenden) -// globalen Nextcloud-Handler. -try { - fwrite(STDERR, "DEBUG: hole UserManager/RootFolder ...\n"); - - // Argumente einlesen: erstes nicht-Options-Argument = Benutzername - // (optional, sonst alle Benutzer). --before=YYYY-MM-DD prueft nur - // Dateien, die VOR diesem Datum zuletzt geaendert wurden - spart bei - // grossen Accounts viel Zeit, sobald der Cutoff-Zeitpunkt bekannt ist. - $onlyUser = null; - $beforeTs = null; - $afterTs = null; - foreach (array_slice($argv, 1) as $arg) { - if (str_starts_with($arg, '--before=')) { - $beforeTs = strtotime(substr($arg, 9)); - } elseif (str_starts_with($arg, '--after=')) { - $afterTs = strtotime(substr($arg, 8)); - } elseif ($onlyUser === null) { - $onlyUser = $arg; - } - } - if ($beforeTs !== null) { - fwrite(STDERR, "DEBUG: Filter --before " . date('Y-m-d', $beforeTs) . "\n"); - } - if ($afterTs !== null) { - fwrite(STDERR, "DEBUG: Filter --after " . date('Y-m-d', $afterTs) . "\n"); - } - - // Neuere Nextcloud-Versionen haben die alten Komfort-Methoden wie - // getUserManager()/getRootFolder() auf \OC::$server entfernt - der - // unterstuetzte Weg ist jetzt der PSR-11-Container ->get(...). - $userManager = \OC::$server->get(\OCP\IUserManager::class); - $rootFolder = \OC::$server->get(\OCP\Files\IRootFolder::class); - fwrite(STDERR, "DEBUG: UserManager/RootFolder OK\n"); - - $total = 0; - $skipped = 0; - $bad = 0; - $usersScanned = 0; - - echo "user\tpath\tsize_bytes\tmtime\terror\n"; - flush(); - - /** - * Rekursiv durch einen Ordner gehen und jede Datei vollstaendig lesen - * (ausser sie liegt ausserhalb von --before/--after). - */ - $scanFolder = function (\OCP\Files\Folder $folder, string $uid) use (&$scanFolder, &$total, &$skipped, &$bad, $beforeTs, $afterTs) { - foreach ($folder->getDirectoryListing() as $node) { - if ($node instanceof \OCP\Files\Folder) { - $scanFolder($node, $uid); - continue; - } - if (!($node instanceof \OCP\Files\File)) { - continue; - } - - $mtimeRaw = $node->getMTime(); - if (($beforeTs !== null && $mtimeRaw >= $beforeTs) || ($afterTs !== null && $mtimeRaw <= $afterTs)) { - $skipped++; - continue; - } - - $total++; - $path = $node->getPath(); - - try { - $stream = $node->fopen('r'); - if ($stream === false) { - throw new \RuntimeException('fopen lieferte false'); - } - while (!feof($stream)) { - $chunk = fread($stream, 8 * 1024 * 1024); - if ($chunk === false) { - throw new \RuntimeException('fread schlug mitten im Stream fehl'); - } - } - fclose($stream); - } catch (\Throwable $e) { - $bad++; - $mtime = date('c', $node->getMTime()); - $msg = str_replace(["\t", "\n", "\r"], ' ', $e->getMessage()); - echo "$uid\t$path\t{$node->getSize()}\t$mtime\t" . get_class($e) . ": $msg\n"; - flush(); - } - } - }; - - $scanUser = function (\OCP\IUser $user) use (&$scanFolder, $rootFolder, &$usersScanned) { - $uid = $user->getUID(); - fwrite(STDERR, "Scanne Benutzer: $uid ...\n"); - - \OC_Util::setupFS($uid); - - try { - $userFolder = $rootFolder->getUserFolder($uid); - } catch (\Throwable $e) { - fwrite(STDERR, " Ueberspringe $uid: kann User-Folder nicht laden (" . $e->getMessage() . ")\n"); - return; - } - - $scanFolder($userFolder, $uid); - $usersScanned++; - }; - - if ($onlyUser !== null) { - fwrite(STDERR, "DEBUG: suche Benutzer '$onlyUser' ...\n"); - $user = $userManager->get($onlyUser); - if ($user === null) { - fwrite(STDERR, "Benutzer '$onlyUser' nicht gefunden.\n"); - exit(1); - } - fwrite(STDERR, "DEBUG: Benutzer gefunden, starte Scan ...\n"); - $scanUser($user); - } else { - $userManager->callForAllUsers($scanUser); - } - - fwrite(STDERR, "\nFertig. Benutzer gescannt: $usersScanned, Dateien geprueft: $total, uebersprungen (Filter): $skipped, fehlgeschlagen: $bad\n"); -} catch (\Throwable $e) { - fwrite(STDERR, "\n!!! UNBEHANDELTE AUSNAHME !!!\n"); - fwrite(STDERR, get_class($e) . ": " . $e->getMessage() . "\n"); - fwrite(STDERR, "in " . $e->getFile() . ":" . $e->getLine() . "\n"); - fwrite(STDERR, $e->getTraceAsString() . "\n"); - exit(2); -} -PHP_SCAN_EOF - -chmod 644 "$scan_php_file" 2> /dev/null - -mkdir -p "$report_dir" 2> /dev/null -report_file="${report_dir}/bad_signature_${WEBSITE}_${run_date}.tsv" - -{ - echo "==================================================================" - echo " Bad-Signature-Scan ${WEBSITE} ${run_date}" - echo "==================================================================" - echo "" - echo -e "user\tpath\tsize_bytes\tmtime\terror" -} > "$report_file" - - -if $terminal ; then - echo "" - echo -e "\033[1;32mStarting Script for \033[1;37m${WEBSITE}\033[m" - echo "" - echo -e " Cloud instance to be scanned.........: $WEBSITE" - echo "" - echo -e " Current version of nextcloud.........: $CURRENT_VERSION" - echo "" - echo -e " Web base directory...................: $WEB_BASE_DIR" - echo -e " Install directory....................: $INSTALL_DIR" - echo -e " Data directory.......................: $DATA_DIR" - echo "" - echo -e " Webserver user.......................: $HTTP_USER" - echo -e " Webserver group......................: $HTTP_GROUP" - echo "" - echo -e " PHP command..........................: $PHP_BIN" - echo "" - echo -e " Account(s) to scan...................: \033[33m${selected_user_arr[*]}\033[m" - echo "" - echo -e " Report file...........................: $report_file" - echo "" - - echo "" - echo -n " Type upper case 'YES' to continue executing with this parameters: " - read OK - if [[ "$OK" = "YES" ]] ; then - echo "" - echo "" - echo -e "\033[1;32mGoing to scan encrypted files for each selected account on \033[1;37m$WEBSITE \033[m" - else - fatal "Abort by user request - Answer as not 'YES'" - fi -fi - - -# ----- -# - Main part of the script -# ----- - -if $terminal ; then - echo "" - echo "" - echo -e "\033[37m\033[1mMain part of the script\033[m" - echo "" -fi - -declare -i total_checked=0 -declare -i total_bad=0 -declare -i total_failed_users=0 - -for _user in "${selected_user_arr[@]}" ; do - - user_tsv="${LOCK_DIR}/scan_${_user}.tsv" - - # - Gut sichtbarer Account-Abschnitt im Reportfile - wird IMMER - # - angelegt, auch wenn der Scan fuer diesen Account fehlschlaegt. - # - - _sep_len=${#_user} - [[ $_sep_len -lt 9 ]] && _sep_len=9 - _sep_line="$(printf '%*s' "$_sep_len" '' | tr ' ' '-')" - - { - echo "" - echo "" - echo "$_sep_line" - echo "$_user" - echo "$_sep_line" - } >> "$report_file" - - echononl " Scanning account \033[1;37m${_user}\033[m.." - su -c "$PHP_BIN $scan_php_file $_user" -s /bin/bash $HTTP_USER > "$user_tsv" 2> "$log_file" - _rc=$? - - if [[ $_rc -ne 0 ]]; then - echo_failed - error "$(cat "$log_file")" - echo " [ FEHLER beim Scan - siehe Server-Log ]" >> "$report_file" - (( total_failed_users++ )) - continue - fi - - # - Kopfzeile weglassen und im Account-Abschnitt anhaengen - # - - tail -n +2 "$user_tsv" >> "$report_file" - - _user_bad=$(tail -n +2 "$user_tsv" | wc -l) - (( total_bad += _user_bad )) - - # - Scan lief durch: bei Funden gelb hervorheben statt schlichtem 'ok' - # - - if [[ $_user_bad -gt 0 ]] ; then - echo_funde - else - echo_ok - fi - - # - Leerzeile NACH der 'Scanning account ..'-Zeile, vor der - # - Account-Statistik. - # - - $terminal && echo "" - - # - Kennzahlen aus der STDERR-Zusammenfassung herausziehen - # - - _summary="$(grep -E '^Fertig\.' "$log_file")" - _checked="$(echo "$_summary" | grep -oE 'Dateien geprueft: [0-9]+' | grep -oE '[0-9]+')" - _skipped="$(echo "$_summary" | grep -oE 'uebersprungen \(Filter\): [0-9]+' | grep -oE '[0-9]+')" - [[ -z "$_skipped" ]] && _skipped="0" - - if [[ "$_checked" =~ ^[0-9]+$ ]] ; then - (( total_checked += _checked )) - _pct="$(calc_percent "$_user_bad" "$_checked")" - else - _checked="?" - _pct="?" - fi - - # - Ergebnis-Block pro Account - gleiches Looking wie das - # - Gesamtergebnis am Ende (Konsole + Reportfile) - # - - if $terminal ; then - echo -e " \033[1;37mAccount ${_user}\033[m" - echo -e " Gescannte Dateien.......................: ${_checked}" - echo -e " Uebersprungene Dateien...................: ${_skipped}" - if [[ $_user_bad -gt 0 ]] ; then - echo -e " Dateien mit 'Bad Signature'..............: \033[1;33m${_user_bad} (${_pct} %)\033[m" - else - echo -e " Dateien mit 'Bad Signature'..............: ${_user_bad} (${_pct} %)" - fi - # - Leerzeile HINTER der Account-Statistik, damit sie nicht am - # - 'Scanning account ..' des naechsten Accounts klebt. - # - - echo "" - fi - - { - echo " Account ${_user}" - echo " Gescannte Dateien.......................: ${_checked}" - echo " Uebersprungene Dateien...................: ${_skipped}" - echo " Dateien mit 'Bad Signature'..............: ${_user_bad} (${_pct} %)" - } >> "$report_file" - -done - -total_pct="$(calc_percent "$total_bad" "$total_checked")" - -# - Gesamtergebnis ans Ende des Reportfiles - gleiches Looking wie -# - die Ergebnis-Bloecke pro Account -# - -{ - echo "" - echo "" - echo "==================================================================" - echo " Gesamtergebnis" - echo "==================================================================" - echo "" - echo "Gescannte Accounts.........................: ${#selected_user_arr[@]}" - [[ $total_failed_users -gt 0 ]] && echo "Accounts mit Scan-Fehler...................: ${total_failed_users}" - echo "Gescannte Dateien insgesamt.................: ${total_checked}" - echo "Dateien mit 'Bad Signature' insgesamt.......: ${total_bad} (${total_pct} %)" -} >> "$report_file" - -blank_line - -if $terminal ; then - echo -e "\033[37m\033[1mErgebnis\033[m" - echo "" - echo -e " Gescannte Accounts.........................: ${#selected_user_arr[@]}" - [[ $total_failed_users -gt 0 ]] && echo -e " Accounts mit Scan-Fehler...................: \033[1;31m${total_failed_users}\033[m" - echo -e " Gescannte Dateien insgesamt.................: ${total_checked}" - echo -e " Dateien mit 'Bad Signature' insgesamt.......: \033[1;31m${total_bad} (${total_pct} %)\033[m" - echo -e " Report-Datei.................................: ${report_file}" - echo "" -fi - -clean_up 0