From feedbd7a3677f4a2990c080fd37b256a12484345 Mon Sep 17 00:00:00 2001 From: Patrick Neumann Date: Tue, 12 Jun 2018 17:31:21 +0200 Subject: [PATCH] added ios2html --- ios2html | 632 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 632 insertions(+) create mode 100644 ios2html diff --git a/ios2html b/ios2html new file mode 100644 index 0000000..510681b --- /dev/null +++ b/ios2html @@ -0,0 +1,632 @@ +#!/usr/bin/env bash +#=============================================================================== +# DIRECTORY: +# --- +# +# FILE: +# ./ios2html +# +# BASIC USAGE: +# $ ./ios2html [-b browser] -c case_no [-f folder] [-h] [-n] [-o officer] [-q] [-v] ios_backup +# OR +# $ bash ios2html ... +# AND MAYBE IN FUTURE ALSO: +# $ ksh ios2html ... +# $ zsh ios2html ... +# $ dash ios2html ... +# $ busybox ash ios2html ... +# +# OPTIONS: +# -b browser: The browser command to use to view the report. +# (default: firefox) +# -c case_no: The Case Number used in the organisation. +# (MANDOTORY!) +# -f folder : The output directory to use for all files. +# (default: report) +# -h : display usage and exit +# -n : disable logging (enabled by default) +# -o officer: The name of the Officer running the case. +# If this is not supplied it is the real name field +# for the current user in /etc/passwd or OpenDirectory. +# -q : disable stdout (enabled by default) +# -v : print version and exit +# ios_backup: source (folder) to process (MANDOTORY!) +# +# EXIT STATES: +# 0 = success +# 1 = (t)csh is not supported +# 2 = python2.7 is not installed +# 3 = functions library missing +# 4 = functions library could not be loaded +# 5 = OS and/or shell not supported +# 6 = additional library missing +# 7 = unrecognised option +# 8 = option requires an argument +# 9 = template_engine could not be loaded +# 10 = bc is not installed +# (for additional codes see libraries!) +# +# DESCRIPTION: +# This script generates multiple html files by processing an ios backup. +# +# REQUIREMENTS: +# date, ... +# +# BUGS: +# - macOS 10.13.4 + dash 0.5.10.2 does not work for any reason!? +# +# TESTS: +# Plaform and shell combinations: +# - OS X (10.13.4) + bash (from Homebrew, NOT the builtin sh) +# - ArchLinux + bash (4.4.19) +# - ArchLinux + busybox ash (1.28.4) +# - ArchLinux + ksh (93v- 2014-06-25) BUT WITH WARNINGS +# - FreeBSD 11.1 + bash 4.4.19 +# ! (t)csh is NOT supported ! +# Sources: +# - physical backup (jailbreak) of an iPhone 5s + iOS 8.1.2 +# - empty backup (folder with just one empty file) +# Tools: +# - shellcheck -s bash -e SC2154,SC1090,SC2086,SC2034,SC2016 ./ios2html +# - shellcheck -s ksh -e SC2154,SC1090,SC2086,SC2034,SC2016 ./ios2html +# - shellcheck -s dash -e SC2154,SC1090,SC2086,SC2034,SC2016 ./ios2html +# +# AUTHOR: +# Patrick Neumann, patrick@neumannsland.de +# +# COAUTHOR(S): +# Odin Heitmann, odin.heitmann@gmail.com +# +# COMPANY: +# (privately) +# +# VERSION: +# 1.1 +# +# LINK TO THE MOST CURRENT VERSION: +# (Sorry, we bet, I'm not allowed to publish it over GitHub!) +# +# CREATED: +# 2018-06-05 +# +# COPYRIGHT (C): +# 2018 - Patrick Neumann & Odin Heitmann +# +# LICENSE: +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# WARRANTY: +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# +# NOTES: +# Followed styleguides: +# - http://lug.fh-swf.de/vim/vim-bash/StyleGuideShell.en.pdf +# - https://google.github.io/styleguide/shell.xml +# +# TODO: +# - wrap too long lines to have 80 chars at maximum +# - swith vars that have to be modified while execution to lowercase +# - different default application list for different devices +# - add other devices than iPhone to the hardware_map.tsv +# - add more pictures of iOS devices +# - add detection/support for logical (advanced) backups +# - add support for Debian, Bash on Ubuntu on Windows 10, ... +# - finish support for zsh, ksh, busybox ash & dash +# +# HISTORY: +# 1.0 - P. N. & O. H. - Initial (for the trainers eyes only) release +# 1.1 - P. N. - added network plugin +# +#=============================================================================== + +#------------------------------------------------------------------------------- +# (t)csh needs too many modifications! +# (different "if" syntax, no conditional command, "set" before var="val",...) +# Worth reading link: http://www.grymoire.com/unix/CshTop10.txt +#------------------------------------------------------------------------------- +# SC2154: ${shell} is referenced but not assigned +# (It's not a bug... it's a feature!) +test -n "${shell}" \ + && printf "\\n\\033[01;31;40mERROR: (t)csh is not supported... EXIT\\!\\!\\!\\033[00m\\n\\n" \ + && exit 1 + +#------------------------------------------------------------------------------- +# Control debugging manually: on or off (and everything else then "on"). +#------------------------------------------------------------------------------- +readonly DEBUG="off" + +#------------------------------------------------------------------------------- +# Start of script as a UNIX timestamp in microseconds. +#------------------------------------------------------------------------------- +# Long line because: +# SC1004: Break outside single quotes if you just want to break the line! +readonly MICRO_START="$( python2.7 -c 'from time import time; print int(round(time() * 1000000));' )" +if [ -z "${MICRO_START}" ] ; then + printf "\\n\\033[01;31;40mERROR: python2.7 not installed... EXIT!!!\\033[00m\\n\\n" + exit 2 +fi + +#------------------------------------------------------------------------------- +# Checking for and including libraries. +#------------------------------------------------------------------------------- +# To have "better" zsh support first import main functions standalone +readonly MAIN_FUNCTIONS="$( dirname "${0}" )/lib/functions.sh" +if ! [ -f "${MAIN_FUNCTIONS}" ] ; then + printf "\\n\\033[01;31;40mERROR: main functions library missing... EXIT!!!\\033[00m\\n\\n" + exit 3 +fi +# In dash, 'source' in place of '.' is not supported! +. "${MAIN_FUNCTIONS}" + +#------------------------------------------------------------------------------- +# Check if functions library is loaded first. +#------------------------------------------------------------------------------- +if [ "${FUNCTIONS_LOADED}" != "true" ] ; then + printf "\\n\\033[01;31;40mERROR: functions library not loaded... EXIT!!!\\033[00m\\n\\n" + exit 4 +fi + +#------------------------------------------------------------------------------- +# Check for unsupported OS + Shell combinations. +#------------------------------------------------------------------------------- +if [ "${OS_NAME}" = "Darwin" ] && [ "${CURRENT_SHELL}" != "bash" ] ; then + error_exit "Sorry, actually only bash is supported on macOS\\!" 5 +fi + +# dash doesn't support arrays! +LIBRARIES="template_engine.sh" +LIBRARIES="${LIBRARIES} hardware_plugin.sh" +LIBRARIES="${LIBRARIES} os_plugin.sh" +LIBRARIES="${LIBRARIES} network_plugin.sh" +LIBRARIES="${LIBRARIES} configuration_plugin.sh" +LIBRARIES="${LIBRARIES} accounts_plugin.sh" +LIBRARIES="${LIBRARIES} applications_plugin.sh" +LIBRARIES="${LIBRARIES} sms_plugin.sh" +LIBRARIES="${LIBRARIES} kik_plugin.sh" +readonly LIBRARIES="${LIBRARIES} addressbook_plugin.sh" +for library in ${LIBRARIES} ; do + # SC1090: "${0%/*}/${library}" is too generic for shellcheck! + if ! [ -f "$( ${BIN_DIRNAME} "${0}" )/lib/${library}" ] ; then + error_exit "\\n\\033[01;31;40mERROR: library ${library} missing... EXIT!!!\\033[00m\\n\\n" 6 + fi + . "$( ${BIN_DIRNAME} "${0}" )/lib/${library}" +done + +#=== CONFIGURATION (static) ==================================================== +readonly VERSION="1.1" +readonly CREATED="2018-06-05" +FOLDER="report" # <- could be modified later! + +assign_binary "date" # common +assign_binary "python2.7" # -> ${BIN_PYTHON27} # common +assign_binary "sed" # common +assign_binary "bc" # uncommon +assign_binary "mv" # common + +#------------------------------------------------------------------------------- +# Check existence of uncommon binaries. +#------------------------------------------------------------------------------- +[ -z "${BIN_BC}" ] && error_exit "please install bc and retry" 10 + +# Change some defaults (functions.sh): +#ECHO_FUNC="display" + +#------------------------------------------------------------------------------- +# Variables as "controllers" for the simple template engine. +#------------------------------------------------------------------------------- +readonly HEAD_TITLE="iOS to HTML" +readonly HEADER_H1="${HEAD_TITLE}" +readonly HEADER_SUBTITLE="... featured by bash, awk, pl(ist)util, sqlite3 & co." + +#=== CONFIGURATION (dynamic) =================================================== +# SC2086: The space(s) in ${DATE_DISPLAY} are important for splitting options! +readonly DATE="$( ${BIN_DATE} ${DATE_DISPLAY}${MICRO_START%??????} )" +readonly SCRIPTNAME="$( ${BIN_BASENAME} "${0}" )" + +#=== FUNCTION ================================================================== +# NAME: usage +# DESCRIPTION: Display help. +# PARAMETERS: - +#=============================================================================== +usage() { + ${BIN_PRINTF} "BASIC USAGE...\\n" + ${BIN_PRINTF} " bash ios2html [-b browser] -c case_no [-f folder] [-h] [-n] [-o officer] [-q] [-v] ios_backup\\n\\n" + ${BIN_PRINTF} "OPTIONS:\\n\\n" + ${BIN_PRINTF} " -b browser: The browser command to use to view the report.\\n" + ${BIN_PRINTF} " (default: firefox)\\n" + ${BIN_PRINTF} " -c case_no: The Case Number used in the organisation.\\n" + ${BIN_PRINTF} " (MANDOTORY!)\\n" + ${BIN_PRINTF} " -f folder : The output directory to use for all files.\\n" + ${BIN_PRINTF} " (default: report)\\n" + ${BIN_PRINTF} " -h : display usage and exit\\n" + ${BIN_PRINTF} " -n : disable logging (enabled by default)\\n" + ${BIN_PRINTF} " -o officer: The name of the Officer running the case.\\n" + ${BIN_PRINTF} " If this is not supplied it is the real name field\\n" + ${BIN_PRINTF} " for the current user in /etc/passwd or OpenDirectory.\\n" + ${BIN_PRINTF} " -q : disable stdout (enabled by default)\\n" + ${BIN_PRINTF} " -v : print version and exit\\n" + ${BIN_PRINTF} " ios_backup: source (folder) to process (MANDOTORY!)\\n\\n" +} + +#------------------------------------------------------------------------------- +# Try to reconstruct the script call. +#------------------------------------------------------------------------------- +CMD_LINE="${0}" +for part in "${@}" ; do +# Using "${@}" instead of ${*} should not lead in space problems!? + CMD_LINE="${CMD_LINE} ${part}" +done + +#=== CONFIGURATION (input) ===================================================== +# (-) GNU- and BSD-getopt behave differently +# (+) getopts is more POSIX and system-/shell-portable +while getopts ":b:c:f:hno:qv" opt ; do + case $opt in + b ) BROWSER="${OPTARG}" # <- could be modified later! + ;; + c ) readonly CASE_NUMBER="${OPTARG}" + ;; + f ) FOLDER="${OPTARG}" # <- could be modified later! + ;; + h ) readonly GET_HELP="yes" ;; + n ) readonly DISABLE_LOGGING="yes" ;; + o ) OFFICER="${OPTARG}" # <- could be modified later! + ;; + q ) readonly DISABLE_STDOUT="yes" ;; + v ) readonly GET_VERSION_ONLY="yes" ;; + \? ) error "unrecognised option (-%s)" "${OPTARG}" + usage + exit 7 + ;; + : ) error "option -%s requires an argument" "${OPTARG}" + usage + exit 8 + ;; + esac +done +LC_ALL="C" shift "$(( OPTIND - 1 ))" + +#=== CONFIGURATION (output) ==================================================== +if [ "${DISABLE_LOGGING}" = "yes" ] ; then + ECHO_FUNC="display" +fi +if [ "${DISABLE_STDOUT}" = "yes" ] ; then + ECHO_FUNC="log" +fi +if [ "${DISABLE_LOGGING}" = "yes" ] && [ "${DISABLE_STDOUT}" = "yes" ] ; then + ECHO_FUNC="quiet" +fi + +#------------------------------------------------------------------------------- +# Just display version, if "-h" or "-v" is given and exit without error code +# if "-v" is given. +#------------------------------------------------------------------------------- +if [ "${GET_HELP}" = "yes" ] || [ "${GET_VERSION_ONLY}" = "yes" ] ; then + ${BIN_PRINTF} "\\n${SCRIPTNAME} version: ${VERSION} (created: ${CREATED})\\n\\n" +else + #------------------------------------------------------------------------------- + # Some checks for folder and logfile. + #------------------------------------------------------------------------------- + check_folder + readonly LOG_FILE="${FOLDER}/ios2html.log" + if [ "${ECHO_FUNC}" = "display_and_log" ] || [ "${ECHO_FUNC}" = "log" ] ; then + check_logfile + # SC2034: all "unused" vars are verified! + readonly LOGFILE_LINK="
  • ios2html.log
  • " + readonly LOGFILE_INFO="Logfile:${LOG_FILE}" + fi + + hint "${SCRIPTNAME} version:\\n ${VERSION} (created: ${CREATED})" + + ${ECHO_FUNC} "\\n" +fi +if [ "${GET_VERSION_ONLY}" = "yes" ] ; then + exit 0 +fi + +#------------------------------------------------------------------------------- +# Just display help, if "-h" is given and exit without error code. +#------------------------------------------------------------------------------- +# make only sence for stdout +if [ "${GET_HELP}" = "yes" ] ; then + usage + exit 0 +fi + +#------------------------------------------------------------------------------- +# Output cmdline. +#------------------------------------------------------------------------------- +hint "Cmdline:\\n ${CMD_LINE}\\n" + +#------------------------------------------------------------------------------- +# Script started at. +#------------------------------------------------------------------------------- +hint "${SCRIPTNAME} started at:\\n ${DATE}\\n" + +#------------------------------------------------------------------------------- +# Loaded libraries and plugins. +#------------------------------------------------------------------------------- +hint "Loaded libraries and plugins:" +hint " functions.sh" +for library in ${LIBRARIES} ; do + hint " ${library}" +done + +${ECHO_FUNC} "\\n" + +#------------------------------------------------------------------------------- +# Display/log some output that we already have. +#------------------------------------------------------------------------------- +hint "System:\\n ${OS_NAME} + ${CURRENT_SHELL}\\n" +hint "Defined/supplied Target folder:\\n ${FOLDER}\\n" +hint "Defined log file:\\n ${LOG_FILE}\\n" + +#------------------------------------------------------------------------------- +# Some more checks. +#------------------------------------------------------------------------------- +check_browser +check_case_number +check_officer +check_source "${1}" + +#------------------------------------------------------------------------------- +# Check if temblate engine library is loaded first. +#------------------------------------------------------------------------------- +if [ "${TEMPLATE_ENGINE_LOADED}" != "true" ] ; then + error_exit "template_engine.sh not loaded" 9 +fi + +#------------------------------------------------------------------------------- +# Create and fill folder. +#------------------------------------------------------------------------------- +init_folder + +#------------------------------------------------------------------------------- +# Create "index.html". +#------------------------------------------------------------------------------- +hint "Start creating index.html...\\n" + +# If the HTMP page is in a subfolder you have to change the prefix to be able +# to load css, html, ... files. +prefix="./" + +top_nav="$( ${BIN_CAT} <<'EOF' +
  • Main
  • +
  • Accounts
  • +
  • Applications
  • +EOF +)" + +render_template "${HEADER}" > "${FOLDER}/index.html" +render_template "${CASE_INFORMATION}" >> "${FOLDER}/index.html" + +#------------------------------------------------------------------------------- +# Add hardware information to "index.html". +#------------------------------------------------------------------------------- +if [ "${HARDWARE_PLUGIN_LOADED}" = "true" ] ; then + hint "... adding hardware informations..." + get_hardware_info + render_template "${HARDWARE_INFORMATION}" >> "${FOLDER}/index.html" + + success "hardware informations added" +fi + +${ECHO_FUNC} "\\n" + +#------------------------------------------------------------------------------- +# Add operating system information to "index.html". +#------------------------------------------------------------------------------- +if [ "${OS_PLUGIN_LOADED}" = "true" ] ; then + hint "... adding os informations..." + get_os_info + render_template "${OS_INFORMATION}" >> "${FOLDER}/index.html" + + success "operating system informations added" +fi + +${ECHO_FUNC} "\\n" + +#------------------------------------------------------------------------------- +# Add network information to "index.html". +#------------------------------------------------------------------------------- +if [ "${NETWORK_PLUGIN_LOADED}" = "true" ] ; then + hint "... adding network informations..." + get_network_info + render_template "${NETWORK_INFORMATION}" >> "${FOLDER}/index.html" + + success "network informations added" +fi + +${ECHO_FUNC} "\\n" + +#------------------------------------------------------------------------------- +# Add configuration information to "index.html". +#------------------------------------------------------------------------------- +if [ "${CONFIGURATION_PLUGIN_LOADED}" = "true" ] ; then + hint "... adding configuration informations..." + get_configuration_info + render_template "${CONFIGURATION_INFORMATION}" >> "${FOLDER}/index.html" + + success "configuration informations added" +fi + +${ECHO_FUNC} "\\n" + +#------------------------------------------------------------------------------- +# Creating "accounts.html". +#------------------------------------------------------------------------------- +if [ "${ACCOUNTS_PLUGIN_LOADED}" = "true" ] ; then + hint "Start creating accounts.html..." + + top_nav="$( ${BIN_CAT} <<'EOF' +
  • Main
  • +
  • Accounts
  • +
  • Applications
  • +EOF + )" + + render_template "${HEADER}" > "${FOLDER}/accounts.html" + get_accounts_list + render_template "${ACCOUNTS_INFORMATION}" >> "${FOLDER}/accounts.html" + render_template "${FOOTER}" >> "${FOLDER}/accounts.html" + + success "accounts.html created" +fi + +${ECHO_FUNC} "\\n" + +#------------------------------------------------------------------------------- +# Creating "applications.html". +#------------------------------------------------------------------------------- +if [ "${APPLICATIONS_PLUGIN_LOADED}" = "true" ] ; then + hint "Start creating applications.html..." + + top_nav="$( ${BIN_CAT} <<'EOF' +
  • Main
  • +
  • Accounts
  • +
  • Applications
  • +EOF + )" + + render_template "${HEADER}" > "${FOLDER}/applications.html" + get_applications_list + render_template "${APPLICATIONS_INFORMATION}" >> "${FOLDER}/applications.html" + render_template "${FOOTER}" >> "${FOLDER}/applications.html" + + success "applications.html created" + + ${ECHO_FUNC} "\\n" + +#------------------------------------------------------------------------------- +# Creating "sms.html". +#------------------------------------------------------------------------------- + if [ "${SMS_PLUGIN_LOADED}" = "true" ] ; then + hint "Start creating sms.html..." + + top_nav="$( ${BIN_CAT} <<'EOF' +
  • Main
  • +
  • Accounts
  • +
  • Applications
  • +EOF +)" + + render_template "${HEADER}" > "${FOLDER}/sms.html" + get_sms_list + render_template "${SMS_INFORMATION}" >> "${FOLDER}/sms.html" + render_template "${FOOTER}" >> "${FOLDER}/sms.html" + +#------------------------------------------------------------------------------- +# Inject hyperlink to "applications.html" +#------------------------------------------------------------------------------- + ${BIN_SED} "s|
  • Messages
  • |
  • Messages
  • |" "${FOLDER}/applications.html" > /tmp/applications.html + ${BIN_MV} /tmp/applications.html "${FOLDER}/applications.html" + + success "sms.html created" + fi + + ${ECHO_FUNC} "\\n" + +#------------------------------------------------------------------------------- +# Creating "contacts.html". +#------------------------------------------------------------------------------- + if [ "${ADDRESSBOOK_PLUGIN_LOADED}" = "true" ] ; then + hint "Start creating contacts.html..." + + top_nav="$( ${BIN_CAT} <<'EOF' +
  • Main
  • +
  • Accounts
  • +
  • Applications
  • +EOF +)" + + render_template "${HEADER}" > "${FOLDER}/contacts.html" + get_addressbook_list + render_template "${ADDRESSBOOK_INFORMATION}" >> "${FOLDER}/contacts.html" + render_template "${FOOTER}" >> "${FOLDER}/contacts.html" + +#------------------------------------------------------------------------------- +# Inject hyperlink to "applications.html" +#------------------------------------------------------------------------------- + ${BIN_SED} "s|
  • Contacts
  • |
  • Contacts
  • |" "${FOLDER}/applications.html" > /tmp/applications.html + ${BIN_MV} /tmp/applications.html "${FOLDER}/applications.html" + + success "contacts.html created" + fi + + ${ECHO_FUNC} "\\n" + +#------------------------------------------------------------------------------- +# Creating "kik.html". +#------------------------------------------------------------------------------- + if [ "${KIK_PLUGIN_LOADED}" = "true" ] ; then + hint "Start creating kik.html..." + + top_nav="$( ${BIN_CAT} <<'EOF' +
  • Main
  • +
  • Accounts
  • +
  • Applications
  • +EOF +)" + + render_template "${HEADER}" > "${FOLDER}/kik.html" + get_kik_list + render_template "${KIK_INFORMATION}" >> "${FOLDER}/kik.html" + render_template "${FOOTER}" >> "${FOLDER}/kik.html" + +#------------------------------------------------------------------------------- +# Inject hyperlink to "applications.html" +#------------------------------------------------------------------------------- + ${BIN_SED} "s|com.kik.chat|com.kik.chat|" "${FOLDER}/applications.html" > /tmp/applications.html + ${BIN_MV} /tmp/applications.html "${FOLDER}/applications.html" + + success "kik.html created" + fi +fi + +${ECHO_FUNC} "\\n" + +render_template "${FOOTER}" >> "${FOLDER}/index.html" +success "index.html created" + +${ECHO_FUNC} "\\n" + +#------------------------------------------------------------------------------- +# Open index.html file in a browser. +#------------------------------------------------------------------------------- +case "${OS_NAME}" in + Darwin) ${BIN_OPEN} -a "${BROWSER}" "${FOLDER}/index.html" + ;; + Linux|FreeBSD) ${BROWSER} "${FOLDER}/index.html" + ;; +esac + +readonly MICRO_STOP="$( ${BIN_PYTHON27} -c 'from time import time; print int(round(time() * 1000000))' )" +readonly MICRO_DELTA="$(( MICRO_STOP - MICRO_START ))" +# printf does not work here +readonly BENCHMARK="$( echo "scale=6; x=${MICRO_DELTA}/1000000; if( x<1 && x>0 ) print 0; x" | ${BIN_BC} )" + +hint "The report was rendered in ${BENCHMARK} seconds." + +#------------------------------------------------------------------------------- +# Remove color codes in logfile. +#------------------------------------------------------------------------------- +# BSDs sed does not know "--in-place"! +# BSDs sed "-i" needs "" and Linux sed "-i" does not! +if [ "${DISABLE_LOGGING}" != "yes" ] ; then + ${BIN_SED} 's/'"$( ${BIN_PRINTF} "\\033" )"'\[01;3[0-9];40m//g' "${LOG_FILE}" \ + > /tmp/ios2html.log + ${BIN_SED} 's/'"$( ${BIN_PRINTF} "\\033" )"'\[00m//g' /tmp/ios2html.log \ + > "${LOG_FILE}" + ${BIN_RM} /tmp/ios2html.log +fi + +exit 0 \ No newline at end of file