From 66900d3f8b63a3ae549cf09ba440d9740116ee8b Mon Sep 17 00:00:00 2001 From: Patrick Neumann Date: Fri, 15 Jun 2018 12:24:10 +0200 Subject: [PATCH] added the one and only main script --- tsk2html | 1115 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 1115 insertions(+) create mode 100644 tsk2html diff --git a/tsk2html b/tsk2html new file mode 100644 index 0000000..095dfc3 --- /dev/null +++ b/tsk2html @@ -0,0 +1,1115 @@ +#!/usr/bin/env bash +#=============================================================================== +# DIRECTORY: +# --- +# +# FILE: +# ./tsk2html +# +# BASIC USAGE: +# $ bash tsk2html [-h] -c case_no [-f folder] [-o officer] [-b browser] image_file +# OR +# $ ./tsk2html ... +# $ ksh tsk2html ... +# $ zsh tsk2html ... +# $ dash tsk2html ... +# $ busybox ash tsk2html ... +# +# OPTIONS: +# -c case_no: The Case Number used in the organisation. +# -f folder : The output directory to use for all files. +# The default value is report. +# -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. +# -b browser: The browser command to use to view the report. +# The default is firefox. +# -h : Displays the help message. +# +# EXIT STATES: +# 0 = success +# 1 = (t)csh is not supported +# 2 = base64 is not installed +# 3 = openssl is not installed +# 4 = sleuthkit is not installed +# 5 = unrecognised option +# 6 = option requires an argument +# 7 = no case number supplied +# 8 = directory already exists +# 9 = unable to create directory +# 10 = os not supportet (default browser) +# 11 = illegal browser command supplied +# 12 = image file argument not supplied +# 13 = image file does not exist +# 14 = image file is not readable +# 15 = image file is writable +# +# DESCRIPTION: +# This script generates multiple html files by processing mmls, fsstat, fls, +# istat and icat (The Sleuth Kit) out of a supplied image. +# +# REQUIREMENTS (Linux): +# awk, base64, basename, cat, date, dirname, file, fls, fsstat, grep, icat, +# img_stat, istat, ln, mkdir, mmls, openssl, printf, ps, sed, stat, tail +# and uname +# +# BUGS: +# --- +# +# NOTES: +# Tested on: +# - ArchLinux + bash, zsh, ksh, busybox ash & dash +# - Debian GNU/Linux 8.x + bash, zsh, ksh, busybox ash & dash +# - Linux Mint 18 (Cinnamon) + bash, zsh, ksh, busybox ash & dash +# - FreeBSD 11 + bash, zsh, ksh93 and dash +# - OS X (10.11.6) + bash (from Homebrew, NOT the builtin sh), zsh, ksh and dash +# - Bash on Ubuntu on Windows 10 (use "-b true") +# ! (t)csh is NOT supported ! +# with: +# - EWF and RAW images +# - filesystem(s) in partition(s) +# - filesystem without a partition +# - no partition/no filesystem (empty file) +# - HFS+, Ext2/3/4, UFS2, Fat12/16/32 and NTFS +# +# AUTHOR: +# Patrick Neumann, patrick@neumannsland.de +# +# COMPANY: +# (privately) +# +# VERSION: +# 1.0 +# +# LINK TO THE MOST CURRENT VERSION: +# (Sorry, I bet, I'm not allowed to publish it over GitHub!) +# +# CREATED: +# 2016-11-11 +# +# COPYRIGHT (C): +# 2016 - Patrick Neumann +# +# 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 . +# +# NOTE: +# --- +# +# TODO: +# - Parted Magic support +# - Split fls into multiple pages (pagination) to support greater images. +# +# HISTORY: +# 1.0 - Patrick Neumann - Initial (for the trainers eyes only) release +# +#=============================================================================== + +#------------------------------------------------------------------------------- +# (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 +#------------------------------------------------------------------------------- +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" + +#=== CONFIGURATION ============================================================= +readonly VERSION="1.0" +readonly CREATED="2016-11-11" + +# Absolute paths are more secure but less portable. +readonly BIN_WHICH="/usr/bin/which" # common + +# Relative paths are more portable but less secure. +readonly BIN_AWK="$( ${BIN_WHICH} "awk" )" # common +readonly BIN_BASE64="$( ${BIN_WHICH} "base64" )" # uncommon +readonly BIN_BASENAME="$( ${BIN_WHICH} "basename" )" # common +readonly BIN_CAT="$( ${BIN_WHICH} "cat" )" # common +readonly BIN_DATE="$( ${BIN_WHICH} "date" )" # common +readonly BIN_DIRNAME="$( ${BIN_WHICH} "dirname" )" # common +readonly BIN_FILE="$( ${BIN_WHICH} "file" )" # common +readonly BIN_FLS="$( ${BIN_WHICH} "fls" )" # sleuthkit +readonly BIN_FSSTAT="$( ${BIN_WHICH} "fsstat" )" # sleuthkit +readonly BIN_GREP="$( ${BIN_WHICH} "grep" )" # common +readonly BIN_ICAT="$( ${BIN_WHICH} "icat" )" # sleuthkit +readonly BIN_IMG_STAT="$( ${BIN_WHICH} "img_stat" )" # sleuthkit +readonly BIN_ISTAT="$( ${BIN_WHICH} "istat" )" # sleuthkit +readonly BIN_LN="$( ${BIN_WHICH} "ln" )" # common +readonly BIN_MKDIR="$( ${BIN_WHICH} "mkdir" )" # common +readonly BIN_MKTEMP="$( ${BIN_WHICH} "mktemp" )" # common +readonly BIN_MMLS="$( ${BIN_WHICH} "mmls" )" # sleuthkit +readonly BIN_OPENSSL="$( ${BIN_WHICH} "openssl" )" # not libressl +readonly BIN_PRINTF="$( ${BIN_WHICH} "printf" )" # common +readonly BIN_PS="$( ${BIN_WHICH} "ps" )" # common +readonly BIN_RM="$( ${BIN_WHICH} "rm" )" # common +readonly BIN_SED="$( ${BIN_WHICH} "sed" )" # common +readonly BIN_STAT="$( ${BIN_WHICH} "stat" )" # common +readonly BIN_UNAME="$( ${BIN_WHICH} "uname" )" # common + +#------------------------------------------------------------------------------- +# Check(s) for the existence of additional mandatory software. +#------------------------------------------------------------------------------- +# uncommon on FreeBSD 11 +if [ -z "${BIN_BASE64}" ] ; then + ${BIN_PRINTF} "\n\033[01;31;40mERROR: please install base64 and retry... EXIT!!!\033[00m\n\n" + exit 2 +fi + +# It's unknown if this script works with libressl +if [ -z "${BIN_OPENSSL}" ] ; then + ${BIN_PRINTF} "\n\033[01;31;40mERROR: please install openssl and retry... EXIT!!!\033[00m\n\n" + exit 3 +fi + +if [ -z "${BIN_IMG_STAT}" ] ; then + ${BIN_PRINTF} "\n\033[01;31;40mERROR: please install sleuthkit and retry... EXIT!!!\033[00m\n\n" + exit 4 +fi + +#------------------------------------------------------------------------------- +# Detect operating system name and react on it. +#------------------------------------------------------------------------------- +readonly OS_NAME="$( ${BIN_UNAME} -s )" + +case "${OS_NAME}" in + Darwin) readonly BIN_ID="$( ${BIN_WHICH} "id" )" # common + readonly BIN_OPEN="$( ${BIN_WHICH} "open" )" # common + readonly SED_EXT_REGEXP="-E" + ;; + Linux) readonly BIN_GETENT="$( ${BIN_WHICH} "getent" )" # common + readonly SED_EXT_REGEXP="--regexp-extended" + ;; + FreeBSD) readonly BIN_GETENT="$( ${BIN_WHICH} "getent" )" # common + readonly SED_EXT_REGEXP="-E" + ;; +esac + +if [ "${DEBUG}" = "on" ] ; then + ${BIN_PRINTF} "OS_NAME: %s\n" "${OS_NAME}" 1>&2 +fi + +#------------------------------------------------------------------------------- +# Detect the shell in which we are running and react on it. +#------------------------------------------------------------------------------- +readonly PROCESS="$( ${BIN_BASENAME} "$( ${BIN_PS} -axco pid,command \ + | ${BIN_GREP} "$$" \ + | ${BIN_GREP} --invert-match "grep" \ + | ${BIN_AWK} '{ print $2; }' )" )" +# Why conditinal command should be prefered over test: +# https://google-styleguide.googlecode.com/svn/trunk/shell.xml#Test,_[_and_[[ +# and why you don't, if you would support "dash": +# http://mywiki.wooledge.org/Bashism +if [ "${PROCESS}" = "$( ${BIN_BASENAME} "${0}" )" ] ; then + readonly CURRENT_SHELL="${DEFAULT_SHELL}" +else + readonly CURRENT_SHELL="${PROCESS}" +fi + +# Linux can have alle shells and "/bin/echo" has no limitations. +# Darwin (14.5.0) has bash 3.2.57, zsh 5.0.5, ksh 93 and tcsh 6.17.00 +# - kshs and tcshs builtin echo does not support "-e" and/or "-n"! +# - "/bin/echo" does not support "-e"! +# FreeBSD can have all shells, but "/bin/echo" has the same limitations! +# Solution: use printf instead! +# Worth readable Link: http://hyperpolyglot.org/unix-shells#echo-note +if [ "${CURRENT_SHELL}" = "zsh" ] ; then + # zsh does not split a string into words separated by spaces by default! + setopt shwordsplit +fi + +if [ "${DEBUG}" = "on" ] ; then + ${BIN_PRINTF} "CURRENT_SHELL: %s\n" "${CURRENT_SHELL}" 1>&2 +fi + +#=== FUNCTION ================================================================== +# NAME: usage +# DESCRIPTION: Display help. +# PARAMETERS: - +#=============================================================================== +usage() { + ${BIN_PRINTF} "\nVersion: %s (created: %s)\n\n" "${VERSION}" "${CREATED}" + ${BIN_PRINTF} "BASIC USAGE...\n" + ${BIN_PRINTF} " bash tsk2html [-h] -c case_no [-f folder] [-o officer] [-b browser] image_file\n\n" + ${BIN_PRINTF} "OPTIONS:\n\n" + ${BIN_PRINTF} " -c case_no: The Case Number used in the organisation.\n" + ${BIN_PRINTF} " -f folder : The output directory to use for all files.\n" + ${BIN_PRINTF} " The default value is report.\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.\n" + ${BIN_PRINTF} " -b browser: The browser command to use to view the report.\n" + ${BIN_PRINTF} " The default is firefox.\n" + ${BIN_PRINTF} " -h : Displays this help message.\n\n" +} + +#=== CONFIGURATION ============================================================= +# (-) GNU- and BSD-getopt behave differently +# (+) getopts is more POSIX and system-/shell-portable +while getopts ":c:f:o:b:h" opt ; do + case $opt in + c ) readonly CASE_NUMBER="${OPTARG}" + ;; + f ) readonly FOLDER="${OPTARG}" + ;; + o ) readonly OFFICER="${OPTARG}" + ;; + b ) BROWSER="${OPTARG}" + ;; + h ) usage + exit 0 + ;; + \? ) ${BIN_PRINTF} "\n\033[01;31;40mERROR: unrecognised option (-%s)... EXIT!!!\033[00m\n" "${OPTARG}" + usage + exit 5 + ;; + : ) ${BIN_PRINTF} "\n\033[01;31;40mERROR: option -%s requires an argument... EXIT!!!\033[00m\n" "${OPTARG}" + usage + exit 6 + ;; + esac +done +LC_ALL="C" shift "$(( OPTIND - 1 ))" + +#------------------------------------------------------------------------------- +# Check for case number. +#------------------------------------------------------------------------------- +if [ -z "${CASE_NUMBER}" ] ; then + ${BIN_PRINTF} "\n\033[01;31;40mERROR: no case number supplied... EXIT!!!\033[00m\n" + usage + exit 7 +fi + +if [ "${DEBUG}" = "on" ] ; then + ${BIN_PRINTF} "CASE_NUMBER: %s\n" "${CASE_NUMBER}" 1>&2 +fi + +#------------------------------------------------------------------------------- +# Check for output folder otherwise use "report". +#------------------------------------------------------------------------------- +if [ -z "${FOLDER}" ] ; then + readonly FOLDER="report" +fi + +if [ -d "${FOLDER}" ] ; then + # I prefere to check for an existing report folder from a previous call + # over "just" check if the folder is empty. + ${BIN_PRINTF} "\n\033[01;31;40mERROR: directory (${FOLDER}) already exists... EXIT!!!\033[00m\n\n" + exit 8 +fi + +if ! [ -w "$( ${BIN_DIRNAME} "${FOLDER}" )" ] ; then + ${BIN_PRINTF} "\n\033[01;31;40mERROR: unable to create directory (${FOLDER})... EXIT!!!\033[00m\n\n" + exit 9 +fi + +if [ "${DEBUG}" = "on" ] ; then + ${BIN_PRINTF} "FOLDER: %s\n" "${FOLDER}" 1>&2 +fi + +#------------------------------------------------------------------------------- +# Check for fullname of the user otherwise use passwd/OpenDirectory. +#------------------------------------------------------------------------------- +if [ -z "${OFFICER}" ] ; then + case "${OS_NAME}" in + Darwin) OFFICER="$( ${BIN_ID} -F )" + ;; + Linux|FreeBSD) OFFICER="$( ${BIN_GETENT} passwd "${LOGNAME}" \ + | cut -d ":" -f 5 | cut -d "," -f 1 )" + ;; + esac + # Sometimes the system don't know the fullname of the user. + # The default in Bash on Ubuntu on Windows 10 is "". + if [ -z "${OFFICER}" -o "${OFFICER}" = "\"\"" ] ; then + readonly OFFICER="unknown" + fi +fi + +if [ "${DEBUG}" = "on" ] ; then + ${BIN_PRINTF} "OFFICER: %s\n" "${OFFICER}" 1>&2 +fi + +#------------------------------------------------------------------------------- +# Check for browser otherwise use firefox. +# (If no Desktop Environment is installed, try "true" as "a browser".) +#------------------------------------------------------------------------------- +if [ -z "${BROWSER}" ] ; then + case "${OS_NAME}" in + Darwin) readonly BROWSER="Firefox" + ;; + Linux|FreeBSD) BROWSER="firefox" + ;; + *) ${BIN_PRINTF} "\n\033[01;31;40mERROR: your os is not supported (yet)... EXIT!!!\033[00m\n\n" + exit 10 + ;; + esac +fi + +case "${OS_NAME}" in + Darwin) if ! [ -d "/Applications/${BROWSER}.app" ] ; then + ${BIN_PRINTF} "\n\033[01;31;40mERROR: illegal browser command (${BROWSER}) supplied... EXIT!!!\033[00m\n\n" + exit 11 + fi + ;; + Linux|FreeBSD) readonly BROWSER="$( ${BIN_WHICH} "${BROWSER}" )" + if ! [ -x "${BROWSER}" ] ; then + ${BIN_PRINTF} "\n\033[01;31;40mERROR: illegal browser command (${BROWSER}) supplied... EXIT!!!\033[00m\n\n" + exit 11 + fi + ;; +esac + +if [ "${DEBUG}" = "on" ] ; then + ${BIN_PRINTF} "BROWSER: %s\n" "${BROWSER}" 1>&2 +fi + +#------------------------------------------------------------------------------- +# Check if image file is given otherwise EXIT. +#------------------------------------------------------------------------------- +if [ -z "${1}" ] ; then + ${BIN_PRINTF} "\n\033[01;31;40mERROR: image file argument not supplied... EXIT!!!\033[00m\n" + usage + exit 12 +fi + +if ! [ -f "${1}" ] ; then + ${BIN_PRINTF} "\n\033[01;31;40mERROR: image file (${1}) does not exist... EXIT!!!\033[00m\n\n" + exit 13 +fi + +if ! [ -r "${1}" ] ; then + ${BIN_PRINTF} "\n\033[01;31;40mERROR: image file (${1}) is not readable... EXIT!!!\033[00m\n\n" + exit 14 +fi + +if [ -w "${1}" ] ; then + ${BIN_PRINTF} "\n\033[01;31;40mERROR: image file (${1}) is writable... EXIT!!!\033[00m\n\n" + exit 15 +fi + +readonly IMAGE_FILE="${1}" +if [ "${DEBUG}" = "on" ] ; then + ${BIN_PRINTF} "IMAGE_FILE: %s\n" "${IMAGE_FILE}" 1>&2 +fi + +#------------------------------------------------------------------------------- +# Create folder (without subfolders because it could be an "empty" image). +#------------------------------------------------------------------------------- +${BIN_MKDIR} "${FOLDER}" + +#------------------------------------------------------------------------------- +# Create a very minimal index.html for later use on a web server. +#------------------------------------------------------------------------------- +${BIN_CAT} < "${FOLDER}/index.html" + + + + + +

Forwarding

+

+ Please click: +
+ main.html +

+ + +EOF + +#------------------------------------------------------------------------------- +# Create the favicon. +#------------------------------------------------------------------------------- +# Into base64 converted binary data could be "a little bit longer". +# "echo" expects longer argument list then printf. +# Freeing some memory afterwards could not be amiss. +FAVICON_BASE64="iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAAN1wAADdcBQiibeAAAABl0RVh0U29mdHdhcmUAd3d3Lmlua3NjYXBlLm9yZ5vuPBoAAAG8SURBVDiNjZM/iBNBFMZ/MzvJunfmYFfwtjgbEzk4jhSKoNa2goiNaGXhCaYRDAiHNlprcYuVhaCNWIj4BxSusBJRhNtDRTF6nCkWPUQMJJe4s2PhBhIvE/yaebz3vY/fDIwwxmBTGMX7JwtSNRbmX9g8yrr9V+ccISYAa4CwEey6sbpDCJpFR6rZwJ19fLzyeZRP2pIni3LBU3IbGNVJs/M2nzXAU3K3pySeknTS7OTZZ+v+fwccuvPhqOuIV64Sy56S9LTxm796i6O8W95g3633xcBTDWOYSY35kRl8bYzwHNkqFWX5/rHy97EEgafqEwU54yqBMQRdnYnf2rCps1JHm0tjCeZuvpvaE7hrG+3U/9rq0dPDdK4jWlOuU1k9PfdtJMGmzupvkrbf+NntLz8A7vbnXW1KG530wkiCMIp3Ag1gez57lNSqR/LZbeBU3m8D5aRWTf4luDywDPBwoH6anwb4AtSHrhBGcRk4w7A+DdRv+8SAC9wbCgCuAoW8XgOuAR8HAprAdWAdqADLYRSfABDTSyt7gdfAE+BKUqu+ZIzCKD4ILAKHgXkxvbRyEXie1KrWHzcm6MAfcSib4f24CrwAAAAASUVORK5CYII=" +echo -n "${FAVICON_BASE64}" | ${BIN_BASE64} --decode > "${FOLDER}/favicon.ico" +FAVICON_BASE64= + +#------------------------------------------------------------------------------- +# Create the logo. +#------------------------------------------------------------------------------- +LOGO_BASE64="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" +echo -n "${LOGO_BASE64}" | ${BIN_BASE64} --decode > "${FOLDER}/polstarlowsax.png" +LOGO_BASE64= + +#------------------------------------------------------------------------------- +# Create the CSS files (customized YAML). +#------------------------------------------------------------------------------- +IEHACKS_BASE64="LyogWWV0IEFub3RoZXIgTXVsdGljb2x1bW4gTGF5b3V0IC0gaHR0cDovL3d3dy55YW1sLmRlICovCkBtZWRpYSBhbGx7Ym9keXtvXHZlcmZsb3c6dmlzaWJsZX1hcnRpY2xlLGFzaWRlLGRldGFpbHMsZmlnY2FwdGlvbixmaWd1cmUsZm9vdGVyLGhlYWRlcixtYWluLG5hdixzZWN0aW9ue3pvb206MX1hdWRpbyxjYW52YXMsdmlkZW97KmRpc3BsYXk6aW5saW5lOyp6b29tOjF9aW1ney1tcy1pbnRlcnBvbGF0aW9uLW1vZGU6YmljdWJpYzt6b29tOjF9KiBodG1sIGlmcmFtZSwqIGh0bWwgZnJhbWV7b3ZlcmZsb3c6YXV0b30qIGh0bWwgaW5wdXQsKiBodG1sIGZyYW1lc2V0e292ZXJmbG93OmhpZGRlbn0qIGh0bWwgdGV4dGFyZWF7b3ZlcmZsb3c6c2Nyb2xsO292ZXJmbG93LXg6aGlkZGVufWJvZHksI21haW57cG9zaXRpb246cmVsYXRpdmV9KiBodG1sIGJvZHl7cG9zaXRpb246c3RhdGljfS55bS1jbGVhcmZpeHt6b29tOjF9KiBodG1sIC55bS1jb2wxLCogaHRtbCAueW0tY29sMiwqIGh0bWwgLnltLWNvbDN7cG9zaXRpb246cmVsYXRpdmV9Ym9keXtoZWlnaHQ6MSV9LnltLXdyYXBwZXIsLnltLXdib3gsI2hlYWRlciwjbmF2LCNtYWluLCNmb290ZXJ7em9vbToxfSogaHRtbCAueW0td3JhcHBlciwqIGh0bWwgLnltLXdib3h7aGVpZ2h0OjElO2hlaVxnaHQ6YXV0b30qIGh0bWwgI2hlYWRlciwqIGh0bWwgI25hdiwqIGh0bWwgI21haW4sKiBodG1sICNmb290ZXJ7d2lkdGg6MTAwJTt3aWRcdGg6YXV0b30ueW0tZ2JveCwueW0tZ2JveC1sZWZ0LC55bS1nYm94LXJpZ2h0e2hlaWdodDoxJX0qIGh0bWwgdWwsKiBodG1sIG9sLCogaHRtbCBkbHtwb3NpdGlvbjpyZWxhdGl2ZX1ib2R5IG9sIGxpe2Rpc3BsYXk6bGlzdC1pdGVtfSogaHRtbCAuZmxleGlibGV7em9vbToxfWJ1dHRvbixpbnB1dHsqb3ZlcmZsb3c6dmlzaWJsZSFpbXBvcnRhbnR9dGFibGUgYnV0dG9uLHRhYmxlIGlucHV0eypvdmVyZmxvdzphdXRvfWZpZWxkc2V0LGxlZ2VuZHtwb3NpdGlvbjpyZWxhdGl2ZX0ueW0tZm9ybSwueW0tZm9ybSBkaXYsLnltLWZvcm0gZGl2ICp7em9vbToxfS55bS1mb3JtIGlucHV0LC55bS1mb3JtIHRleHRhcmVhe3dpZHRoOjY4JTtwYWRkaW5nLWxlZnQ6MSUhaW1wb3J0YW50O3BhZGRpbmctcmlnaHQ6MSUhaW1wb3J0YW50fS55bS1mb3JtIHNlbGVjdHt3aWR0aDo3MCU7cGFkZGluZy1sZWZ0OjElIWltcG9ydGFudDtwYWRkaW5nLXJpZ2h0OjElIWltcG9ydGFudH0ueW0tZm9ybSAueW0tZmJveC13cmFwe2Rpc3BsYXk6YmxvY2s7b3ZlcmZsb3c6aGlkZGVuO21hcmdpbi1yaWdodDotNXB4fS55bS1mYm94LXdyYXAgaW5wdXQsLnltLWZib3gtd3JhcCB0ZXh0YXJlYSwueW0tZnVsbCBpbnB1dCwueW0tZnVsbCB0ZXh0YXJlYXt3aWR0aDo5OCU7bWFyZ2luLXJpZ2h0Oi0zcHh9LnltLWZib3gtd3JhcCBzZWxlY3QsLnltLWZ1bGwgc2VsZWN0e3dpZHRoOjEwMCU7bWFyZ2luLXJpZ2h0Oi0zcHh9KiBodG1sIC55bS1mb3JtIC55bS1mYm94LWNoZWNrIGlucHV0e2Rpc3BsYXk6aW5saW5lIWltcG9ydGFudDt3aWR0aDphdXRvIWltcG9ydGFudDtiYWNrZ3JvdW5kOnRyYW5zcGFyZW50IWltcG9ydGFudDtib3JkZXI6MCBub25lIWltcG9ydGFudDtwYWRkaW5nOjAhaW1wb3J0YW50fSogaHRtbCAueW0tZm9ybSAueW0tZmJveC13cmFwIC55bS1mYm94LWNoZWNrIGlucHV0e21hcmdpbi1sZWZ0OjB9aHRtbCAueW0taWUtY2xlYXJpbmd7cG9zaXRpb246c3RhdGljO2Rpc3BsYXk6YmxvY2s7XGNsZWFyOmJvdGg7d2lkdGg6MTAwJTtsaW5lLWhlaWdodDowO2ZvbnQtc2l6ZTowO21hcmdpbjotMnB4IDAgLTFlbSAxcHh9KiBodG1sIC55bS1pZS1jbGVhcmluZ3ttYXJnaW46LTJweCAwIC0xZW0gMH0ueW0tY2JveHttYXJnaW4tYm90dG9tOi0ycHh9aHRtbHttYXJnaW4tcmlnaHQ6MXB4fSogaHRtbHttYXJnaW4tcmlnaHQ6MH0ueW0tY29sM3twb3NpdGlvbjpyZWxhdGl2ZX19QG1lZGlhIHNjcmVlbixwcm9qZWN0aW9uey55bS1jb2wxLC55bS1jb2wye2Rpc3BsYXk6aW5saW5lfS55bS1ncmlke292ZXJmbG93OmhpZGRlbjtkaXNwbGF5OmJsb2NrfSogaHRtbCAueW0tZ3JpZHtvdmVyZmxvdzp2aXNpYmxlfS55bS1nbCwueW0tZ3J7ZGlzcGxheTppbmxpbmV9LnltLWVxdWFsaXplIC55bS1nbHtmbG9hdDpsZWZ0O2Rpc3BsYXk6aW5saW5lO3BhZGRpbmctYm90dG9tOjMyNzY3cHg7bWFyZ2luLWJvdHRvbTotMzI3NjdweH0ueW0tZXF1YWxpemUgLnltLWdye2Zsb2F0OnJpZ2h0O21hcmdpbi1sZWZ0Oi01cHg7ZGlzcGxheTppbmxpbmU7cGFkZGluZy1ib3R0b206MzI3NjdweDttYXJnaW4tYm90dG9tOi0zMjc2N3B4fS5uby1pZS1wYWRkaW5nIC55bS1nbCwubm8taWUtcGFkZGluZyAueW0tZ3J7cGFkZGluZy1ib3R0b206MDttYXJnaW4tYm90dG9tOjB9KiBodG1sIC55bS1jYm94LWxlZnQsKiBodG1sIC55bS1jYm94LXJpZ2h0LCogaHRtbCAueW0tY2JveHt3b3JkLXdyYXA6YnJlYWstd29yZH0qIGh0bWwgLnltLWdib3gsKiBodG1sIC55bS1nYm94LWxlZnQsKiBodG1sIC55bS1nYm94LXJpZ2h0e3dvcmQtd3JhcDpicmVhay13b3JkO29cdmVyZmxvdzpoaWRkZW59fUBtZWRpYSBwcmludHsueW0tZ2JveCwueW0tZ2JveC1sZWZ0LC55bS1nYm94LXJpZ2h0LC55bS1jb2wze2hlaWdodDoxJX19" +echo -n "${IEHACKS_BASE64}" | ${BIN_BASE64} --decode > "${FOLDER}/iehacks.min.css" +IEHACKS_BASE64= + +THEME_BASE64="LyogWWV0IEFub3RoZXIgTXVsdGljb2x1bW4gTGF5b3V0IC0gaHR0cDovL3d3dy55YW1sLmRlICovCkBpbXBvcnQgdXJsKGh0dHA6Ly9mb250cy5nb29nbGVhcGlzLmNvbS9jc3M/ZmFtaWx5PURyb2lkK1NlcmlmOjQwMCw0MDBpdGFsaWMsNzAwfERyb2lkK1NhbnM6NzAwKTsKQG1lZGlhIGFsbHsqe21hcmdpbjowO3BhZGRpbmc6MH1vcHRpb257cGFkZGluZy1sZWZ0Oi40ZW19c2VsZWN0e3BhZGRpbmc6MXB4fSogaHRtbCBib2R5ICp7b3ZlcmZsb3c6dmlzaWJsZX1ib2R5e2ZvbnQtc2l6ZToxMDAlO2JhY2tncm91bmQ6I2ZmZjtjb2xvcjojMDAwO3RleHQtYWxpZ246bGVmdH1kaXY6dGFyZ2V0LGgxOnRhcmdldCxoMjp0YXJnZXQsaDM6dGFyZ2V0LGg0OnRhcmdldCxoNTp0YXJnZXQsaDY6dGFyZ2V0e291dGxpbmU6MCBub25lfWFydGljbGUsYXNpZGUsZGV0YWlscyxmaWdjYXB0aW9uLGZpZ3VyZSxmb290ZXIsaGVhZGVyLG1haW4sbmF2LHNlY3Rpb24sc3VtbWFyeXtkaXNwbGF5OmJsb2NrfWF1ZGlvLGNhbnZhcyx2aWRlb3tkaXNwbGF5OmlubGluZS1ibG9ja31hdWRpbzpub3QoW2NvbnRyb2xzXSl7ZGlzcGxheTpub25lfVtoaWRkZW5de2Rpc3BsYXk6bm9uZX1odG1sey1tcy10ZXh0LXNpemUtYWRqdXN0OjEwMCU7LXdlYmtpdC10ZXh0LXNpemUtYWRqdXN0OjEwMCV9aW5wdXRbdHlwZT1jaGVja2JveF0saW5wdXRbdHlwZT1yYWRpb117Ym94LXNpemluZzpib3JkZXItYm94O3BhZGRpbmc6MH1pbnB1dFt0eXBlPXNlYXJjaF17LXdlYmtpdC1hcHBlYXJhbmNlOnRleHRmaWVsZDstd2Via2l0LWJveC1zaXppbmc6Y29udGVudC1ib3g7LW1vei1ib3gtc2l6aW5nOmNvbnRlbnQtYm94O2JveC1zaXppbmc6Y29udGVudC1ib3h9aW5wdXRbdHlwZT1zZWFyY2hdOjotd2Via2l0LXNlYXJjaC1jYW5jZWwtYnV0dG9uLGlucHV0W3R5cGU9c2VhcmNoXTo6LXdlYmtpdC1zZWFyY2gtZGVjb3JhdGlvbnstd2Via2l0LWFwcGVhcmFuY2U6bm9uZX1zdmc6bm90KDpyb290KXtvdmVyZmxvdzpoaWRkZW59ZmlndXJle21hcmdpbjowfWZpZWxkc2V0LGltZ3tib3JkZXI6MCBzb2xpZH11bCxvbCxkbHttYXJnaW46MCAwIDFlbSAxZW19bGl7bGluZS1oZWlnaHQ6MS41ZW07bWFyZ2luLWxlZnQ6LjhlbX1kdHtmb250LXdlaWdodDo3MDB9ZGR7bWFyZ2luOjAgMCAxZW0gLjhlbX1ibG9ja3F1b3Rle21hcmdpbjowIDAgMWVtIC44ZW19cXtxdW90ZXM6bm9uZX1ibG9ja3F1b3RlOmJlZm9yZSxibG9ja3F1b3RlOmFmdGVyLHE6YmVmb3JlLHE6YWZ0ZXJ7Y29udGVudDoiIjtjb250ZW50Om5vbmV9dGFibGV7Ym9yZGVyLWNvbGxhcHNlOmNvbGxhcHNlO2JvcmRlci1zcGFjaW5nOjB9LnltLWNsZWFyZml4OmJlZm9yZXtjb250ZW50OiIiO2Rpc3BsYXk6dGFibGV9LnltLWNsZWFyZml4OmFmdGVye2NsZWFyOmJvdGg7Y29udGVudDoiLiI7ZGlzcGxheTpibG9jaztmb250LXNpemU6MDtoZWlnaHQ6MDt2aXNpYmlsaXR5OmhpZGRlbn0ueW0tY29udGFpbi1kdHtkaXNwbGF5OnRhYmxlO3RhYmxlLWxheW91dDpmaXhlZDt3aWR0aDoxMDAlfS55bS1jb250YWluLW9oe2Rpc3BsYXk6YmxvY2s7b3ZlcmZsb3c6aGlkZGVuO3dpZHRoOjEwMCV9LnltLWNvbnRhaW4tZmx7ZmxvYXQ6bGVmdDt3aWR0aDoxMDAlfS55bS1jb2x1bW57ZGlzcGxheTp0YWJsZTt0YWJsZS1sYXlvdXQ6Zml4ZWQ7d2lkdGg6MTAwJX0ueW0tY29sMXtmbG9hdDpsZWZ0O3dpZHRoOjIwJX0ueW0tY29sMntmbG9hdDpyaWdodDt3aWR0aDoyMCV9LnltLWNvbDN7d2lkdGg6YXV0bzttYXJnaW46MCAyMCV9LnltLWNib3h7cGFkZGluZzowIDEwcHh9LnltLWNib3gtbGVmdHtwYWRkaW5nOjAgMTBweCAwIDB9LnltLWNib3gtcmlnaHR7cGFkZGluZzowIDAgMCAxMHB4fS55bS1pZS1jbGVhcmluZ3tkaXNwbGF5Om5vbmV9LnltLWdyaWR7ZGlzcGxheTp0YWJsZTt0YWJsZS1sYXlvdXQ6Zml4ZWQ7d2lkdGg6MTAwJTtsaXN0LXN0eWxlLXR5cGU6bm9uZTtwYWRkaW5nLWxlZnQ6MDtwYWRkaW5nLXJpZ2h0OjA7bWFyZ2luLWxlZnQ6MDttYXJnaW4tcmlnaHQ6MH0ueW0tZ2x7ZmxvYXQ6bGVmdDttYXJnaW46MH0ueW0tZ3J7ZmxvYXQ6cmlnaHQ7bWFyZ2luOjAgMCAwIC01cHh9LnltLWcyMHt3aWR0aDoyMCV9LnltLWc0MHt3aWR0aDo0MCV9LnltLWc2MHt3aWR0aDo2MCV9LnltLWc4MHt3aWR0aDo4MCV9LnltLWcyNXt3aWR0aDoyNSV9LnltLWczM3t3aWR0aDozMy4zMzMlfS55bS1nNTB7d2lkdGg6NTAlfS55bS1nNjZ7d2lkdGg6NjYuNjY2JX0ueW0tZzc1e3dpZHRoOjc1JX0ueW0tZzM4e3dpZHRoOjM4LjIlfS55bS1nNjJ7d2lkdGg6NjEuOCV9LnltLWdib3h7cGFkZGluZzowIDEwcHh9LnltLWdib3gtbGVmdHtwYWRkaW5nOjAgMTBweCAwIDB9LnltLWdib3gtcmlnaHR7cGFkZGluZzowIDAgMCAxMHB4fS55bS1lcXVhbGl6ZXtvdmVyZmxvdzpoaWRkZW59LnltLWVxdWFsaXplPltjbGFzcyo9eW0tZ117ZGlzcGxheTp0YWJsZS1jZWxsO2Zsb2F0Om5vbmU7bWFyZ2luOjA7dmVydGljYWwtYWxpZ246dG9wfS55bS1lcXVhbGl6ZT5bY2xhc3MqPXltLWddPltjbGFzcyo9eW0tZ2JveF17cGFkZGluZy1ib3R0b206MTAwMDBweDttYXJnaW4tYm90dG9tOi0xMDAwMHB4fS55bS1mb3JtLC55bS1mb3JtIGZpZWxkc2V0e292ZXJmbG93OmhpZGRlbn0ueW0tZm9ybSBkaXZ7cG9zaXRpb246cmVsYXRpdmV9LnltLWZvcm0gbGFiZWwsLnltLWZvcm0gLnltLWxhYmVsLC55bS1mb3JtIC55bS1tZXNzYWdle3Bvc2l0aW9uOnJlbGF0aXZlO2xpbmUtaGVpZ2h0OjEuNTtkaXNwbGF5OmJsb2NrfS55bS1mb3JtIC55bS1tZXNzYWdle2NsZWFyOmJvdGh9LnltLWZvcm0gLnltLWZib3gtY2hlY2sgbGFiZWx7ZGlzcGxheTppbmxpbmV9LnltLWZvcm0gaW5wdXQsLnltLWZvcm0gdGV4dGFyZWF7Y3Vyc29yOnRleHR9LnltLWZvcm0gLnltLWZib3gtY2hlY2sgaW5wdXQsLnltLWZvcm0gaW5wdXRbdHlwZT1pbWFnZV0sLnltLWZvcm0gaW5wdXRbdHlwZT1yYWRpb10sLnltLWZvcm0gaW5wdXRbdHlwZT1jaGVja2JveF0sLnltLWZvcm0gc2VsZWN0LC55bS1mb3JtIGxhYmVse2N1cnNvcjpwb2ludGVyfS55bS1mb3JtIHRleHRhcmVhe292ZXJmbG93OmF1dG99LnltLWZvcm0gaW5wdXQuaGlkZGVuLC55bS1mb3JtIGlucHV0W3R5cGU9aGlkZGVuXXtkaXNwbGF5Om5vbmUhaW1wb3J0YW50fS55bS1mb3JtIC55bS1mYm94OmJlZm9yZSwueW0tZm9ybSAueW0tZmJveC10ZXh0OmJlZm9yZSwueW0tZm9ybSAueW0tZmJveC1zZWxlY3Q6YmVmb3JlLC55bS1mb3JtIC55bS1mYm94LWNoZWNrOmJlZm9yZSwueW0tZm9ybSAueW0tZmJveC1idXR0b246YmVmb3Jle2NvbnRlbnQ6IiI7ZGlzcGxheTp0YWJsZX0ueW0tZm9ybSAueW0tZmJveDphZnRlciwueW0tZm9ybSAueW0tZmJveC10ZXh0OmFmdGVyLC55bS1mb3JtIC55bS1mYm94LXNlbGVjdDphZnRlciwueW0tZm9ybSAueW0tZmJveC1jaGVjazphZnRlciwueW0tZm9ybSAueW0tZmJveC1idXR0b246YWZ0ZXJ7Y2xlYXI6Ym90aDtjb250ZW50OiIuIjtkaXNwbGF5OmJsb2NrO2ZvbnQtc2l6ZTowO2hlaWdodDowO3Zpc2liaWxpdHk6aGlkZGVufS55bS1mb3JtIC55bS1mYm94LWNoZWNrIGlucHV0OmZvY3VzLC55bS1mb3JtIC55bS1mYm94LWNoZWNrIGlucHV0OmhvdmVyLC55bS1mb3JtIC55bS1mYm94LWNoZWNrIGlucHV0OmFjdGl2ZSwueW0tZm9ybSBpbnB1dFt0eXBlPXJhZGlvXTpmb2N1cywueW0tZm9ybSBpbnB1dFt0eXBlPXJhZGlvXTpob3ZlciwueW0tZm9ybSBpbnB1dFt0eXBlPXJhZGlvXTphY3RpdmUsLnltLWZvcm0gaW5wdXRbdHlwZT1jaGVja2JveF06Zm9jdXMsLnltLWZvcm0gaW5wdXRbdHlwZT1jaGVja2JveF06aG92ZXIsLnltLWZvcm0gaW5wdXRbdHlwZT1jaGVja2JveF06YWN0aXZle2JvcmRlcjowIG5vbmV9LnltLWZvcm0gaW5wdXQsLnltLWZvcm0gdGV4dGFyZWEsLnltLWZvcm0gc2VsZWN0e2Rpc3BsYXk6YmxvY2s7cG9zaXRpb246cmVsYXRpdmU7LXdlYmtpdC1ib3gtc2l6aW5nOmJvcmRlci1ib3g7LW1vei1ib3gtc2l6aW5nOmJvcmRlci1ib3g7Ym94LXNpemluZzpib3JkZXItYm94O3dpZHRoOjcwJX0ueW0tZm9ybSAueW0tZmJveC1jaGVjayBpbnB1dCwueW0tZm9ybSBpbnB1dFt0eXBlPXJhZGlvXSwueW0tZm9ybSBpbnB1dFt0eXBlPWNoZWNrYm94XXtkaXNwbGF5OmlubGluZTttYXJnaW4tbGVmdDowO21hcmdpbi1yaWdodDouNWV4O3dpZHRoOmF1dG87aGVpZ2h0OmF1dG99LnltLWZvcm0gaW5wdXRbdHlwZT1pbWFnZV17Ym9yZGVyOjA7ZGlzcGxheTppbmxpbmU7aGVpZ2h0OmF1dG87bWFyZ2luOjA7cGFkZGluZzowO3dpZHRoOmF1dG99LnltLWZvcm0gbGFiZWwsLnltLWZvcm0gLnltLWxhYmVsey13ZWJraXQtYm94LXNpemluZzpib3JkZXItYm94Oy1tb3otYm94LXNpemluZzpib3JkZXItYm94O2JveC1zaXppbmc6Ym9yZGVyLWJveH0ueW0tZm9ybSAueW0tZmJveC1idXR0b24gaW5wdXR7ZGlzcGxheTppbmxpbmU7b3ZlcmZsb3c6dmlzaWJsZTt3aWR0aDphdXRvfS55bS1mb3JtIC55bS1pbmxpbmV7ZGlzcGxheTppbmxpbmUtYmxvY2s7ZmxvYXQ6bm9uZTttYXJnaW4tcmlnaHQ6MDt3aWR0aDphdXRvO3ZlcnRpY2FsLWFsaWduOmJhc2VsaW5lfS55bS1mYm94LXdyYXB7ZGlzcGxheTp0YWJsZTt0YWJsZS1sYXlvdXQ6Zml4ZWQ7d2lkdGg6NzAlfS55bS1mYm94LXdyYXAgaW5wdXQsLnltLWZib3gtd3JhcCB0ZXh0YXJlYSwueW0tZmJveC13cmFwIHNlbGVjdHt3aWR0aDoxMDAlfS55bS1mYm94LXdyYXAgaW5wdXRbdHlwZT1pbWFnZV17d2lkdGg6YXV0b30ueW0tZmJveC13cmFwIGlucHV0W3R5cGU9cmFkaW9dLC55bS1mYm94LXdyYXAgaW5wdXRbdHlwZT1jaGVja2JveF17ZGlzcGxheTppbmxpbmU7d2lkdGg6YXV0bzttYXJnaW4tbGVmdDowO21hcmdpbi1yaWdodDouNWV4fS55bS1mYm94LXdyYXAgbGFiZWwsLnltLWZib3gtd3JhcCAueW0tbGFiZWx7ZGlzcGxheTppbmxpbmV9LnltLWZ1bGwgaW5wdXQsLnltLWZ1bGwgdGV4dGFyZWEsLnltLWZ1bGwgc2VsZWN0e3dpZHRoOjEwMCV9LnltLWZ1bGwgLnltLWZib3gtd3JhcHt3aWR0aDoxMDAlfS55bS1jb2x1bW5hciBpbnB1dCwueW0tY29sdW1uYXIgdGV4dGFyZWEsLnltLWNvbHVtbmFyIHNlbGVjdHtmbG9hdDpsZWZ0O21hcmdpbi1yaWdodDotM3B4fS55bS1jb2x1bW5hciBsYWJlbCwueW0tY29sdW1uYXIgLnltLWxhYmVse2Rpc3BsYXk6aW5saW5lO2Zsb2F0OmxlZnQ7d2lkdGg6MzAlO3otaW5kZXg6MX0ueW0tY29sdW1uYXIgLnltLWZib3gtY2hlY2sgaW5wdXQsLnltLWNvbHVtbmFyIC55bS1tZXNzYWdle21hcmdpbi1sZWZ0OjMwJX0ueW0tY29sdW1uYXIgLnltLWZib3gtd3JhcHttYXJnaW4tbGVmdDozMCU7bWFyZ2luLXJpZ2h0Oi0zcHh9LnltLWNvbHVtbmFyIC55bS1mYm94LXdyYXAgLnltLW1lc3NhZ2V7bWFyZ2luLWxlZnQ6MH0ueW0tY29sdW1uYXIgLnltLWZib3gtd3JhcCBsYWJlbHtmbG9hdDpub25lO3dpZHRoOmF1dG87ei1pbmRleDoxO21hcmdpbi1sZWZ0OjB9LnltLWNvbHVtbmFyIC55bS1mYm94LXdyYXAgaW5wdXR7bWFyZ2luLWxlZnQ6MDtwb3NpdGlvbjpyZWxhdGl2ZX0ueW0tY29sdW1uYXIgLnltLWZib3gtY2hlY2t7cG9zaXRpb246cmVsYXRpdmV9LnltLWNvbHVtbmFyIC55bS1mYm94LWNoZWNrIGxhYmVsLC55bS1jb2x1bW5hciAueW0tZmJveC1jaGVjayAueW0tbGFiZWx7cGFkZGluZy10b3A6MH0ueW0tY29sdW1uYXIgLnltLWZib3gtY2hlY2sgaW5wdXR7dG9wOjNweH0ueW0tY29sdW1uYXIgLnltLWZib3gtYnV0dG9uIGlucHV0e2Zsb2F0Om5vbmU7bWFyZ2luLXJpZ2h0OjFlbX0ueW0tZmJveC13cmFwKy55bS1mYm94LXdyYXB7bWFyZ2luLXRvcDouNWVtfS55bS1jb2x1bW5hciBmaWVsZHNldCAueW0tZmJveC1idXR0b24sZmllbGRzZXQueW0tY29sdW1uYXIgLnltLWZib3gtYnV0dG9ue3BhZGRpbmctbGVmdDozMCV9LnltLXNraXAsLnltLWhpZGVtZSwueW0tcHJpbnR7cG9zaXRpb246YWJzb2x1dGU7dG9wOi0zMjc2OHB4O2xlZnQ6LTMyNzY4cHh9LnltLXNraXA6Zm9jdXMsLnltLXNraXA6YWN0aXZle3Bvc2l0aW9uOnN0YXRpYzt0b3A6MDtsZWZ0OjB9LnltLXNraXBsaW5rc3twb3NpdGlvbjphYnNvbHV0ZTt0b3A6MDtsZWZ0Oi0zMjc2OHB4O3otaW5kZXg6MTAwMDt3aWR0aDoxMDAlO21hcmdpbjowO3BhZGRpbmc6MDtsaXN0LXN0eWxlLXR5cGU6bm9uZX0ueW0tc2tpcGxpbmtzIC55bS1za2lwOmZvY3VzLC55bS1za2lwbGlua3MgLnltLXNraXA6YWN0aXZle2xlZnQ6MzI3NjhweDtvdXRsaW5lOjAgbm9uZTtwb3NpdGlvbjphYnNvbHV0ZTt3aWR0aDoxMDAlfX1AbWVkaWEgcHJpbnR7LnltLWdyaWQ+LnltLWdsLC55bS1ncmlkPi55bS1ncntvdmVyZmxvdzp2aXNpYmxlO2Rpc3BsYXk6dGFibGU7dGFibGUtbGF5b3V0OmZpeGVkfS55bS1wcmludHtwb3NpdGlvbjpzdGF0aWM7bGVmdDowfS55bS1ub3ByaW50e2Rpc3BsYXk6bm9uZSFpbXBvcnRhbnR9fQpAbWVkaWEgYWxsey55bS1obGlzdHt3aWR0aDoxMDAlO292ZXJmbG93OmhpZGRlbjtwb3NpdGlvbjpyZWxhdGl2ZTtsaW5lLWhlaWdodDoxZW07YmFja2dyb3VuZDojMjIyfS55bS1obGlzdCB1bHttYXJnaW46MDtwYWRkaW5nOi41ZW0gMS41ZW07ZGlzcGxheTppbmxpbmU7ZmxvYXQ6bGVmdH0ueW0taGxpc3QgdWwgbGl7ZGlzcGxheTppbmxpbmU7ZmxvYXQ6bGVmdDtmb250LXNpemU6MWVtO2xpbmUtaGVpZ2h0OjE7bGlzdC1zdHlsZS10eXBlOm5vbmU7bWFyZ2luOjAgLjI1ZW0gMCAwO3BhZGRpbmc6MH0ueW0taGxpc3QgdWwgbGkgYSwueW0taGxpc3QgdWwgbGkgc3Ryb25ne2JhY2tncm91bmQ6dHJhbnNwYXJlbnQ7Y29sb3I6I2FhYTtkaXNwbGF5OmJsb2NrO2ZvbnQtc2l6ZToxZW07bGluZS1oZWlnaHQ6MmVtO3BhZGRpbmc6MCAuNWVtO2ZvbnQtd2VpZ2h0OjQwMDt0ZXh0LWRlY29yYXRpb246bm9uZTt0ZXh0LXNoYWRvdzowIDFweCAxcHggcmdiYSgwLDAsMCwuNSk7d2lkdGg6YXV0b30ueW0taGxpc3QgdWwgbGkgYTpmb2N1cywueW0taGxpc3QgdWwgbGkgYTpob3ZlciwueW0taGxpc3QgdWwgbGkgYTphY3RpdmV7Y29sb3I6I2NjYztiYWNrZ3JvdW5kOiM2NjY7YmFja2dyb3VuZDpyZ2JhKDI1NSwyNTUsMjU1LC4yNSk7Ym9yZGVyLXJhZGl1czouMmVtO3RleHQtZGVjb3JhdGlvbjpub25lO291dGxpbmU6MCBub25lfS55bS1obGlzdCB1bCBsaS5hY3RpdmV7YmFja2dyb3VuZDojNjY2O2JhY2tncm91bmQ6cmdiYSgyNTUsMjU1LDI1NSwuMyk7Ym9yZGVyLXJhZGl1czouMmVtO2NvbG9yOiNmZmZ9LnltLWhsaXN0IHVsIGxpLmFjdGl2ZSBzdHJvbmcsLnltLWhsaXN0IHVsIGxpLmFjdGl2ZSBhOmZvY3VzLC55bS1obGlzdCB1bCBsaS5hY3RpdmUgYTpob3ZlciwueW0taGxpc3QgdWwgbGkuYWN0aXZlIGE6YWN0aXZle2JhY2tncm91bmQ6dHJhbnNwYXJlbnQ7Y29sb3I6I2ZmZjt0ZXh0LWRlY29yYXRpb246bm9uZX0ueW0tc2VhcmNoZm9ybXtmbG9hdDpyaWdodDtkaXNwbGF5OmlubGluZTtsaW5lLWhlaWdodDoyO3BhZGRpbmc6LjVlbSAxLjVlbX0ueW0tc2VhcmNoZm9ybSAueW0tc2VhcmNoZmllbGR7LXdlYmtpdC1hcHBlYXJhbmNlOm5vbmU7YmFja2dyb3VuZDojZmZmO2xpbmUtaGVpZ2h0OjE7cGFkZGluZzouMjVlbTt3aWR0aDoxMmVtO2JvcmRlcjpzb2xpZCAxcHggIzg4ODtib3JkZXI6c29saWQgMXB4IHJnYmEoMjU1LDI1NSwyNTUsLjEpO291dGxpbmU6bm9uZTstd2Via2l0LWJveC1zaGFkb3c6aW5zZXQgMCAxcHggM3B4IHJnYmEoMCwwLDAsLjIpO2JveC1zaGFkb3c6aW5zZXQgMCAxcHggM3B4IHJnYmEoMCwwLDAsLjIpfS55bS1zZWFyY2hmb3JtIC55bS1zZWFyY2hidXR0b257LXdlYmtpdC1hcHBlYXJhbmNlOm5vbmU7YmFja2dyb3VuZDojNWY1ZjVmO2JhY2tncm91bmQ6cmdiYSgyNTUsMjU1LDI1NSwuMik7Ym9yZGVyLXJhZGl1czouMmVtO2NvbG9yOiNmZmY7Y3Vyc29yOnBvaW50ZXI7ZGlzcGxheTppbmxpbmUtYmxvY2s7Zm9udC1zaXplOjFlbTtsaW5lLWhlaWdodDoxLjI1O3BhZGRpbmc6LjI1ZW07Ym9yZGVyOnNvbGlkIDFweCB0cmFuc3BhcmVudDt0ZXh0LXNoYWRvdzowIDFweCAxcHggcmdiYSgwLDAsMCwuNSl9fQpAbWVkaWEgYWxse2h0bWwgKntmb250LXNpemU6MTAwJX10ZXh0YXJlYSxwcmUsY29kZSxrYmQsc2FtcCx2YXIsdHR7Zm9udC1mYW1pbHk6Q29uc29sYXMsIkx1Y2lkYSBDb25zb2xlIiwiQW5kYWxlIE1vbm8iLCJCaXRzdHJlYW0gVmVyYSBTYW5zIE1vbm8iLCJDb3VyaWVyIE5ldyIsQ291cmllcn1ib2R5e2ZvbnQtZmFtaWx5OiJEcm9pZCBTZXJpZiIsR2VvcmdpYSwiVGltZXMgTmV3IFJvbWFuIixUaW1lcyxzZXJpZjtmb250LXNpemU6ODcuNSU7Y29sb3I6IzQ0NH1oMSxoMixoMyxoNCxoNSxoNntmb250LWZhbWlseToiRHJvaWQgU2FucyIsQXJpYWwsSGVsdmV0aWNhLHNhbnMtc2VyaWY7Zm9udC13ZWlnaHQ6NDAwO2NvbG9yOiMxNjFlMjE7bWFyZ2luOjB9aDF7Zm9udC1zaXplOjM0Mi44NTcxNCU7bGluZS1oZWlnaHQ6Ljg3NTttYXJnaW46MCAwIC40Mzc1ZW0gMH1oMntmb250LXNpemU6MjI4LjU3MTQzJTtsaW5lLWhlaWdodDoxLjMxMjU7bWFyZ2luOjAgMCAuNjU2MjVlbSAwfWgze2ZvbnQtc2l6ZToxNzEuNDI4NTclO2xpbmUtaGVpZ2h0Oi44NzU7bWFyZ2luOjAgMCAuODc1ZW0gMH1oNHtmb250LXNpemU6MTUwJTtsaW5lLWhlaWdodDoxO21hcmdpbjowIDAgMWVtIDB9aDV7Zm9udC1zaXplOjEyOC41NzE0MyU7bGluZS1oZWlnaHQ6MS4xNjY2NzttYXJnaW46MCAwIDEuMTY2NjdlbSAwfWg2e2ZvbnQtc2l6ZToxMDAlO2ZvbnQtd2VpZ2h0OjcwMDtsaW5lLWhlaWdodDoxLjU7bWFyZ2luOjAgMCAxLjVlbSAwfXVsLG9sLGRse2ZvbnQtc2l6ZToxMDAlO2xpbmUtaGVpZ2h0OjEuNTttYXJnaW46MCAwIDEuNWVtIDB9dWx7bGlzdC1zdHlsZS10eXBlOmRpc2N9b2x7bGlzdC1zdHlsZS10eXBlOmRlY2ltYWx9dWwgdWx7bGlzdC1zdHlsZS10eXBlOmNpcmNsZTttYXJnaW4tdG9wOjB9b2wgb2x7bGlzdC1zdHlsZS10eXBlOmxvd2VyLWxhdGluO21hcmdpbi10b3A6MH1vbCB1bHtsaXN0LXN0eWxlLXR5cGU6Y2lyY2xlO21hcmdpbi10b3A6MH1saXtmb250LXNpemU6MTAwJTtsaW5lLWhlaWdodDoxLjU7bWFyZ2luLWxlZnQ6MS4yZW19ZHR7Zm9udC13ZWlnaHQ6NzAwfWRke21hcmdpbjowIDAgMS41ZW0gLjhlbX1we2ZvbnQtc2l6ZToxMDAlO2xpbmUtaGVpZ2h0OjEuNTttYXJnaW46MCAwIDEuNWVtIDB9YmxvY2txdW90ZSxjaXRlLHF7Zm9udC1mYW1pbHk6IkRyb2lkIFNlcmlmIixHZW9yZ2lhLCJUaW1lcyBOZXcgUm9tYW4iLFRpbWVzLHNlcmlmO2ZvbnQtc3R5bGU6aXRhbGljfWJsb2NrcXVvdGV7YmFja2dyb3VuZDp0cmFuc3BhcmVudDtjb2xvcjojNjY2O21hcmdpbjoxLjVlbSAwIDAgMS41ZW19c3Ryb25nLGJ7Zm9udC13ZWlnaHQ6NzAwfWVtLGl7Zm9udC1zdHlsZTppdGFsaWN9Ymlne2ZvbnQtc2l6ZToxMTQuMjg1NzElO2xpbmUtaGVpZ2h0OjEuMzEyNX1zbWFsbHtmb250LXNpemU6ODUuNzE0MjklO2xpbmUtaGVpZ2h0OjEuNzV9cHJlLGNvZGUsa2JkLHR0LHNhbXAsdmFye2ZvbnQtc2l6ZToxMDAlfXByZXtmb250LXNpemU6MTAwJTtsaW5lLWhlaWdodDoxLjU7bWFyZ2luOjAgMCAxLjVlbSAwO3doaXRlLXNwYWNlOnByZTt3aGl0ZS1zcGFjZTpwcmUtd3JhcDt3b3JkLXdyYXA6YnJlYWstd29yZH1wcmUsY29kZXtjb2xvcjojODAwfWtiZCxzYW1wLHZhcix0dHtjb2xvcjojNjY2O2ZvbnQtd2VpZ2h0OjcwMH12YXIsZGZue2ZvbnQtc3R5bGU6aXRhbGljfWFjcm9ueW0sYWJicntib3JkZXItYm90dG9tOjFweCAjYWFhIGRvdHRlZDtmb250LXZhcmlhbnQ6c21hbGwtY2FwcztsZXR0ZXItc3BhY2luZzouMDdlbTtjdXJzb3I6aGVscH1zdWIsc3Vwe2ZvbnQtc2l6ZTo3NSU7bGluZS1oZWlnaHQ6MDtwb3NpdGlvbjpyZWxhdGl2ZTt2ZXJ0aWNhbC1hbGlnbjpiYXNlbGluZX1zdXB7dG9wOi0uNWVtfXN1Yntib3R0b206LS4yNWVtfW1hcmt7YmFja2dyb3VuZDp5ZWxsb3c7Y29sb3I6YmxhY2t9aHJ7Y29sb3I6I2ZmZjtiYWNrZ3JvdW5kOnRyYW5zcGFyZW50O21hcmdpbjowIDAgLjc1ZW0gMDtwYWRkaW5nOjAgMCAuNjc4NTdlbSAwO2JvcmRlcjowO2JvcmRlci1ib3R0b206MXB4ICNlZWUgc29saWR9YXtjb2xvcjojNGQ4N2M3O2JhY2tncm91bmQ6dHJhbnNwYXJlbnQ7dGV4dC1kZWNvcmF0aW9uOm5vbmV9YTphY3RpdmV7b3V0bGluZTpub25lfWE6aG92ZXIsYTpmb2N1c3tiYWNrZ3JvdW5kLWNvbG9yOiM0ZDg3Yzc7Y29sb3I6d2hpdGU7dGV4dC1kZWNvcmF0aW9uOm5vbmV9aW1nLGZpZ3VyZXttYXJnaW46MH0uZmxleGlibGV7bWFyZ2luLWJvdHRvbToxLjVlbTttYXgtd2lkdGg6MTAwJTtoZWlnaHQ6YXV0b30qIGh0bWwgLmZsZXhpYmxle3dpZHRoOjk4JX0uYm9yZGVyZWR7bWFyZ2luLWJvdHRvbToxLjVlbTtib3JkZXI6MnB4ICNlZWUgc29saWQ7Ym9yZGVyOjJweCB3aGl0ZSBzb2xpZDstd2Via2l0LWJveC1zaGFkb3c6MCAwIDNweCByZ2JhKDAsMCwwLC4yNSk7Ym94LXNoYWRvdzowIDAgM3B4IHJnYmEoMCwwLDAsLjI1KX0uaGlnaGxpZ2h0e2NvbG9yOiNjMzB9LmRpbW1lZHtjb2xvcjojODg4fS5ib3h7Ym9yZGVyLXJhZGl1czouM2VtO2JvcmRlci13aWR0aDoxcHg7Ym9yZGVyLXN0eWxlOnNvbGlkO2JvcmRlci1jb2xvcjojODg4O2JvcmRlci1jb2xvcjpyZ2JhKDAsMCwwLC4zKTstd2Via2l0LWJveC1zaGFkb3c6aW5zZXQgMXB4IDFweCAzcHggcmdiYSgwLDAsMCwuMik7Ym94LXNoYWRvdzppbnNldCAxcHggMXB4IDNweCByZ2JhKDAsMCwwLC4yKTtjb2xvcjojNDQ0O2NvbG9yOnJnYmEoMCwwLDAsLjgpO3BhZGRpbmc6MS40Mjg1N2VtO21hcmdpbjowIDAgMS41ZW0gMH0uYm94Pio6bGFzdC1jaGlsZHttYXJnaW4tYm90dG9tOjB9LmxhYmVse2ZvbnQtZmFtaWx5OlZlcmRhbmEsR2VuZXZhLHNhbnMtc2VyaWY7cGFkZGluZzoxcHggNnB4IDJweDtkaXNwbGF5OmlubGluZS1ibG9jazt2ZXJ0aWNhbC1hbGlnbjptaWRkbGU7bGV0dGVyLXNwYWNpbmc6bm9ybWFsO3doaXRlLXNwYWNlOm5vd3JhcDtib3JkZXItcmFkaXVzOjNweDtiYWNrZ3JvdW5kOiMwNkM7Y29sb3I6I2ZmZjtmb250LXNpemU6MTBweDtsaW5lLWhlaWdodDoxMnB4fS5pbmZve2JhY2tncm91bmQ6I2Y0ZjRmNH0uc3VjY2Vzc3tiYWNrZ3JvdW5kOiM4Yzh9Lndhcm5pbmd7YmFja2dyb3VuZDojY2M4fS5lcnJvcntiYWNrZ3JvdW5kOiNjODh9LmZsb2F0LWxlZnR7ZmxvYXQ6bGVmdDtkaXNwbGF5OmlubGluZTttYXJnaW46MCAxZW0gMS41ZW0gMH0uZmxvYXQtcmlnaHR7ZmxvYXQ6cmlnaHQ7ZGlzcGxheTppbmxpbmU7bWFyZ2luOjAgMCAxLjVlbSAxZW19LmNlbnRlcntkaXNwbGF5OmJsb2NrO3RleHQtYWxpZ246Y2VudGVyO21hcmdpbjowIGF1dG8gMS41ZW0gYXV0b310YWJsZXt3aWR0aDoxMDAlO2JvcmRlci1jb2xsYXBzZTpjb2xsYXBzZTtjb2xvcjojNDQ0O2JvcmRlci10b3A6MXB4ICNjY2Mgc29saWQ7Ym9yZGVyLWJvdHRvbToxcHggI2NjYyBzb2xpZDttYXJnaW46MCAwIDEuMzU3MTRlbSAwfXRhYmxlLm5hcnJvd3ttYXJnaW46MCAwIDEuNDI4NTdlbSAwfXRhYmxlLm5hcnJvdyB0aCx0YWJsZS5uYXJyb3cgdGR7cGFkZGluZzowIC41ZW07bGluZS1oZWlnaHQ6MS40Mjg1N310YWJsZS5maXhlZHt0YWJsZS1sYXlvdXQ6Zml4ZWR9dGFibGUuYm9yZGVydGFibGV7Ym9yZGVyOjFweCAjY2NjIHNvbGlkfXRhYmxlLmJvcmRlcnRhYmxlIHRoZWFkIHRoe2JhY2tncm91bmQ6I2UwZTBlMDtib3JkZXItcmlnaHQ6MXB4ICNjY2Mgc29saWQ7Ym9yZGVyLWJvdHRvbToxcHggI2NjYyBzb2xpZH10YWJsZS5ib3JkZXJ0YWJsZSB0Ym9keSB0aFtzY29wZT0icm93Il17YmFja2dyb3VuZDojZjBmMGYwfXRhYmxlLmJvcmRlcnRhYmxlIHRib2R5IHRoe2JvcmRlci1yaWdodDoxcHggc29saWQgI2NjY310YWJsZS5ib3JkZXJ0YWJsZSB0Ym9keSB0ZHtib3JkZXItcmlnaHQ6MXB4IHNvbGlkICNjY2N9Y2FwdGlvbntmb250LXZhcmlhbnQ6c21hbGwtY2Fwc310aCx0ZHtsaW5lLWhlaWdodDoxLjVlbTt2ZXJ0aWNhbC1hbGlnbjp0b3A7cGFkZGluZzouNzE0MjllbSAuNWVtfXRoICo6Zmlyc3QtY2hpbGQsdGQgKjpmaXJzdC1jaGlsZHttYXJnaW4tdG9wOjB9dGgubm93cmFwLHRkLm5vd3JhcHt3aGl0ZS1zcGFjZTpub3dyYXB9dGhlYWQgdGh7dGV4dC1hbGlnbjpsZWZ0O2NvbG9yOiMwMDA7Ym9yZGVyLWJvdHRvbToycHggIzAwMCBzb2xpZH10Ym9keSB0aHt0ZXh0LWFsaWduOmxlZnQ7Ym9yZGVyLXRvcDoxcHggc29saWQgI2NjY310Ym9keSB0ZHt0ZXh0LWFsaWduOmxlZnQ7Ym9yZGVyLXRvcDoxcHggc29saWQgI2NjY310Ym9keSB0cjpob3ZlciB0aCx0Ym9keSB0cjpob3ZlciB0ZHtiYWNrZ3JvdW5kOiNmOGY4Zjh9fQpAbWVkaWEgc2NyZWVue2JvZHl7b3ZlcmZsb3cteTpzY3JvbGx9LnltLXdyYXBwZXJ7bWluLXdpZHRoOjc2MHB4O21heC13aWR0aDo4MGVtO21hcmdpbjowIGF1dG99LnltLXdib3h7cGFkZGluZzoxMHB4fWhlYWRlcntiYWNrZ3JvdW5kOiM0NDQ7Y29sb3I6I2NjYztwYWRkaW5nOjEuNWVtfWhlYWRlciBoMXtiYWNrZ3JvdW5kOnRyYW5zcGFyZW50O2NvbG9yOiNmZmZ9bmF2e2JhY2tncm91bmQ6IzIyMn1tYWlue3BhZGRpbmc6MS41ZW0gMCAwIDB9Zm9vdGVye21hcmdpbjowO2JhY2tncm91bmQ6I2VlZTtjb2xvcjojNDQ0O3BhZGRpbmc6MS41ZW19Zm9vdGVyIHB7bWFyZ2luOjB9LnltLWNvbHVtbntkaXNwbGF5OmJsb2NrO292ZXJmbG93OmhpZGRlbjtwYWRkaW5nLXJpZ2h0OjM0MHB4O3dpZHRoOmF1dG99LnltLWNvbDF7ZmxvYXQ6bGVmdDt3aWR0aDoxMDAlfS55bS1jb2wze3Bvc2l0aW9uOnJlbGF0aXZlO2Zsb2F0OmxlZnQ7d2lkdGg6MzQwcHg7bWFyZ2luLWxlZnQ6MDttYXJnaW4tcmlnaHQ6LTM0MHB4fS55bS1jb2wxIC55bS1jYm94e3BhZGRpbmc6MCAuNzVlbSAwIDEuNWVtfS55bS1jb2wzIC55bS1jYm94e3BhZGRpbmc6MCAyMHB4IDAgMTJweH0ueW0tZ2JveHtwYWRkaW5nOjAgMS41ZW0gMCAwfS55bS1za2lwbGlua3MgYS55bS1za2lwOmZvY3VzLC55bS1za2lwbGlua3MgYS55bS1za2lwOmFjdGl2ZXtjb2xvcjojZmZmO2JhY2tncm91bmQ6IzMzMztib3JkZXItYm90dG9tOjFweCAjMDAwIHNvbGlkO3BhZGRpbmc6MTBweCAwO3RleHQtYWxpZ246Y2VudGVyO3RleHQtZGVjb3JhdGlvbjpub25lfX1AbWVkaWEgc2NyZWVuIGFuZCAobWluLXdpZHRoOjApey55bS13cmFwcGVye21pbi13aWR0aDowfX1AbWVkaWEgc2NyZWVuIGFuZCAobWF4LXdpZHRoOjc2MHB4KXsubGluZWFyaXplLWxldmVsLTEsLmxpbmVhcml6ZS1sZXZlbC0xPltjbGFzcyo9InltLWMiXSwubGluZWFyaXplLWxldmVsLTE+W2NsYXNzKj0ieW0tZyJde2Rpc3BsYXk6YmxvY2s7ZmxvYXQ6bm9uZTtwYWRkaW5nOjA7bWFyZ2luOjA7d2lkdGg6YXV0byFpbXBvcnRhbnR9LmxpbmVhcml6ZS1sZXZlbC0xPltjbGFzcyo9InltLWMiXT5bY2xhc3MqPSJ5bS1jYm94Il0sLmxpbmVhcml6ZS1sZXZlbC0xPltjbGFzcyo9InltLWciXT5bY2xhc3MqPSJ5bS1nYm94Il17bWFyZ2luOjA7cGFkZGluZzowO292ZXJmbG93OmhpZGRlbn1uYXYgLnltLWhsaXN0IHVse3BhZGRpbmctcmlnaHQ6MTBweH0ueW0tc2VhcmNoZm9ybXtkaXNwbGF5OmJsb2NrO2Zsb2F0Om5vbmU7d2lkdGg6YXV0bztwYWRkaW5nLXJpZ2h0OjEwcHg7dGV4dC1hbGlnbjpyaWdodH0ueW0tc2VhcmNoZm9ybSBpbnB1dFt0eXBlPSJzZWFyY2giXXt3aWR0aDoxNCV9fUBtZWRpYSBzY3JlZW4gYW5kIChtYXgtd2lkdGg6NDgwcHgpey55bS13Ym94e3BhZGRpbmc6MH1oZWFkZXJ7cGFkZGluZzouNzVlbSAxMHB4fWhlYWRlciBoMXtmb250LXNpemU6MS41ZW07bGluZS1oZWlnaHQ6MWVtO21hcmdpbjowfWZvb3RlcixtYWluLC55bS1zZWFyY2hmb3JtLG5hdiAueW0taGxpc3QgdWx7cGFkZGluZy1sZWZ0OjEwcHg7cGFkZGluZy1yaWdodDoxMHB4fS5saW5lYXJpemUtbGV2ZWwtMiwubGluZWFyaXplLWxldmVsLTI+W2NsYXNzKj0ieW0tYyJdLC5saW5lYXJpemUtbGV2ZWwtMj5bY2xhc3MqPSJ5bS1nIl17ZGlzcGxheTpibG9jaztmbG9hdDpub25lO3BhZGRpbmc6MDttYXJnaW46MDt3aWR0aDphdXRvIWltcG9ydGFudH0ubGluZWFyaXplLWxldmVsLTI+W2NsYXNzKj0ieW0tYyJdPltjbGFzcyo9InltLWNib3giXSwubGluZWFyaXplLWxldmVsLTI+W2NsYXNzKj0ieW0tZyJdPltjbGFzcyo9InltLWdib3giXXttYXJnaW46MDtwYWRkaW5nOjA7b3ZlcmZsb3c6aGlkZGVufS55bS1zZWFyY2hmb3JtLG5hdiAueW0taGxpc3QgdWwsbmF2IC55bS1obGlzdCBsaXtkaXNwbGF5OmJsb2NrO2Zsb2F0Om5vbmU7d2lkdGg6YXV0bzt0ZXh0LWFsaWduOmxlZnR9LnltLXNlYXJjaGZvcm0gaW5wdXRbdHlwZT0ic2VhcmNoIl17d2lkdGg6NzUlfX0KQG1lZGlhIHByaW50e2JvZHl7Zm9udC1zaXplOjEwcHQ7cGFkZGluZzowIDVweH1uYXYsLnltLXNlYXJjaGZvcm17ZGlzcGxheTpub25lfWgxLGgyLGgzLGg0LGg1LGg2e3BhZ2UtYnJlYWstYWZ0ZXI6YXZvaWR9fQ==" +echo -n "${THEME_BASE64}" | ${BIN_BASE64} --decode > "${FOLDER}/theme.css" +THEME_BASE64= + +${BIN_CAT} <> "${FOLDER}/theme.css" + +/* Individual customizations */ +.ym-wrapper { + max-width: 74em; +} +header { + background: #fff; + padding: 0em; + background: rgba(0,0,0,0) + url("polstarlowsax.png") + no-repeat scroll left center; + padding-left: 84px; + height: 72px; +} +header h1 { + padding-top: 7px; + color: #000; +} +h1 { + margin: 0; +} +.ym-hlist { + border-top: 1px solid; + background: #fff; + border-bottom: 1px solid; +} +.ym-hlist ul li a:focus, +.ym-hlist ul li a:hover, +.ym-hlist ul li a:active { + background: rgba(0, 0, 0, 0.25); +} +.ym-hlist ul li.active strong, +.ym-hlist ul li.active a:focus, +.ym-hlist ul li.active a:hover, +.ym-hlist ul li.active a:active { + color: #fff; +} +.ym-hlist ul li.active { + background: rgba(0, 0, 0, 0.3); +} +.ym-hlist ul li a, +.ym-hlist ul li strong { + color: #000; + text-shadow: 0 0px 0px; +} +.ym-hlist ul li a:focus, +.ym-hlist ul li a:hover, +.ym-hlist ul li a:active { + color: #fff; +} +footer { + border-top: 1px solid; + background: #fff; + color: #000; + padding: 0em; +} +footer p { + padding-top: 7px; +} +EOF + +#------------------------------------------------------------------------------- +# Create the JS files (HTML5 support for older Microsoft Internet Explorer +# and skiplink support for Apple Safari). +# (Skiplinks actually seems to be broken, eventually the next YAML release +# will fix this?) +#------------------------------------------------------------------------------- +HTML5SHIV_BASE64="LyoqCiogQHByZXNlcnZlIEhUTUw1IFNoaXYgMy43LjMgfCBAYWZhcmthcyBAamRhbHRvbiBAam9uX25lYWwgQHJlbSB8IE1JVC9HUEwyIExpY2Vuc2VkCiovCiFmdW5jdGlvbihhLGIpe2Z1bmN0aW9uIGMoYSxiKXt2YXIgYz1hLmNyZWF0ZUVsZW1lbnQoInAiKSxkPWEuZ2V0RWxlbWVudHNCeVRhZ05hbWUoImhlYWQiKVswXXx8YS5kb2N1bWVudEVsZW1lbnQ7cmV0dXJuIGMuaW5uZXJIVE1MPSJ4PHN0eWxlPiIrYisiPC9zdHlsZT4iLGQuaW5zZXJ0QmVmb3JlKGMubGFzdENoaWxkLGQuZmlyc3RDaGlsZCl9ZnVuY3Rpb24gZCgpe3ZhciBhPXQuZWxlbWVudHM7cmV0dXJuInN0cmluZyI9PXR5cGVvZiBhP2Euc3BsaXQoIiAiKTphfWZ1bmN0aW9uIGUoYSxiKXt2YXIgYz10LmVsZW1lbnRzOyJzdHJpbmciIT10eXBlb2YgYyYmKGM9Yy5qb2luKCIgIikpLCJzdHJpbmciIT10eXBlb2YgYSYmKGE9YS5qb2luKCIgIikpLHQuZWxlbWVudHM9YysiICIrYSxqKGIpfWZ1bmN0aW9uIGYoYSl7dmFyIGI9c1thW3FdXTtyZXR1cm4gYnx8KGI9e30scisrLGFbcV09cixzW3JdPWIpLGJ9ZnVuY3Rpb24gZyhhLGMsZCl7aWYoY3x8KGM9YiksbClyZXR1cm4gYy5jcmVhdGVFbGVtZW50KGEpO2R8fChkPWYoYykpO3ZhciBlO3JldHVybiBlPWQuY2FjaGVbYV0/ZC5jYWNoZVthXS5jbG9uZU5vZGUoKTpwLnRlc3QoYSk/KGQuY2FjaGVbYV09ZC5jcmVhdGVFbGVtKGEpKS5jbG9uZU5vZGUoKTpkLmNyZWF0ZUVsZW0oYSksIWUuY2FuSGF2ZUNoaWxkcmVufHxvLnRlc3QoYSl8fGUudGFnVXJuP2U6ZC5mcmFnLmFwcGVuZENoaWxkKGUpfWZ1bmN0aW9uIGgoYSxjKXtpZihhfHwoYT1iKSxsKXJldHVybiBhLmNyZWF0ZURvY3VtZW50RnJhZ21lbnQoKTtjPWN8fGYoYSk7Zm9yKHZhciBlPWMuZnJhZy5jbG9uZU5vZGUoKSxnPTAsaD1kKCksaT1oLmxlbmd0aDtpPmc7ZysrKWUuY3JlYXRlRWxlbWVudChoW2ddKTtyZXR1cm4gZX1mdW5jdGlvbiBpKGEsYil7Yi5jYWNoZXx8KGIuY2FjaGU9e30sYi5jcmVhdGVFbGVtPWEuY3JlYXRlRWxlbWVudCxiLmNyZWF0ZUZyYWc9YS5jcmVhdGVEb2N1bWVudEZyYWdtZW50LGIuZnJhZz1iLmNyZWF0ZUZyYWcoKSksYS5jcmVhdGVFbGVtZW50PWZ1bmN0aW9uKGMpe3JldHVybiB0LnNoaXZNZXRob2RzP2coYyxhLGIpOmIuY3JlYXRlRWxlbShjKX0sYS5jcmVhdGVEb2N1bWVudEZyYWdtZW50PUZ1bmN0aW9uKCJoLGYiLCJyZXR1cm4gZnVuY3Rpb24oKXt2YXIgbj1mLmNsb25lTm9kZSgpLGM9bi5jcmVhdGVFbGVtZW50O2guc2hpdk1ldGhvZHMmJigiK2QoKS5qb2luKCkucmVwbGFjZSgvW1x3XC06XSsvZyxmdW5jdGlvbihhKXtyZXR1cm4gYi5jcmVhdGVFbGVtKGEpLGIuZnJhZy5jcmVhdGVFbGVtZW50KGEpLCdjKCInK2ErJyIpJ30pKyIpO3JldHVybiBufSIpKHQsYi5mcmFnKX1mdW5jdGlvbiBqKGEpe2F8fChhPWIpO3ZhciBkPWYoYSk7cmV0dXJuIXQuc2hpdkNTU3x8a3x8ZC5oYXNDU1N8fChkLmhhc0NTUz0hIWMoYSwiYXJ0aWNsZSxhc2lkZSxkaWFsb2csZmlnY2FwdGlvbixmaWd1cmUsZm9vdGVyLGhlYWRlcixoZ3JvdXAsbWFpbixuYXYsc2VjdGlvbntkaXNwbGF5OmJsb2NrfW1hcmt7YmFja2dyb3VuZDojRkYwO2NvbG9yOiMwMDB9dGVtcGxhdGV7ZGlzcGxheTpub25lfSIpKSxsfHxpKGEsZCksYX12YXIgayxsLG09IjMuNy4zIixuPWEuaHRtbDV8fHt9LG89L148fF4oPzpidXR0b258bWFwfHNlbGVjdHx0ZXh0YXJlYXxvYmplY3R8aWZyYW1lfG9wdGlvbnxvcHRncm91cCkkL2kscD0vXig/OmF8Ynxjb2RlfGRpdnxmaWVsZHNldHxoMXxoMnxoM3xoNHxoNXxoNnxpfGxhYmVsfGxpfG9sfHB8cXxzcGFufHN0cm9uZ3xzdHlsZXx0YWJsZXx0Ym9keXx0ZHx0aHx0cnx1bCkkL2kscT0iX2h0bWw1c2hpdiIscj0wLHM9e307IWZ1bmN0aW9uKCl7dHJ5e3ZhciBhPWIuY3JlYXRlRWxlbWVudCgiYSIpO2EuaW5uZXJIVE1MPSI8eHl6PjwveHl6PiIsaz0iaGlkZGVuImluIGEsbD0xPT1hLmNoaWxkTm9kZXMubGVuZ3RofHxmdW5jdGlvbigpe2IuY3JlYXRlRWxlbWVudCgiYSIpO3ZhciBhPWIuY3JlYXRlRG9jdW1lbnRGcmFnbWVudCgpO3JldHVybiJ1bmRlZmluZWQiPT10eXBlb2YgYS5jbG9uZU5vZGV8fCJ1bmRlZmluZWQiPT10eXBlb2YgYS5jcmVhdGVEb2N1bWVudEZyYWdtZW50fHwidW5kZWZpbmVkIj09dHlwZW9mIGEuY3JlYXRlRWxlbWVudH0oKX1jYXRjaChjKXtrPSEwLGw9ITB9fSgpO3ZhciB0PXtlbGVtZW50czpuLmVsZW1lbnRzfHwiYWJiciBhcnRpY2xlIGFzaWRlIGF1ZGlvIGJkaSBjYW52YXMgZGF0YSBkYXRhbGlzdCBkZXRhaWxzIGRpYWxvZyBmaWdjYXB0aW9uIGZpZ3VyZSBmb290ZXIgaGVhZGVyIGhncm91cCBtYWluIG1hcmsgbWV0ZXIgbmF2IG91dHB1dCBwaWN0dXJlIHByb2dyZXNzIHNlY3Rpb24gc3VtbWFyeSB0ZW1wbGF0ZSB0aW1lIHZpZGVvIix2ZXJzaW9uOm0sc2hpdkNTUzpuLnNoaXZDU1MhPT0hMSxzdXBwb3J0c1Vua25vd25FbGVtZW50czpsLHNoaXZNZXRob2RzOm4uc2hpdk1ldGhvZHMhPT0hMSx0eXBlOiJkZWZhdWx0IixzaGl2RG9jdW1lbnQ6aixjcmVhdGVFbGVtZW50OmcsY3JlYXRlRG9jdW1lbnRGcmFnbWVudDpoLGFkZEVsZW1lbnRzOmV9O2EuaHRtbDU9dCxqKGIpLCJvYmplY3QiPT10eXBlb2YgbW9kdWxlJiZtb2R1bGUuZXhwb3J0cyYmKG1vZHVsZS5leHBvcnRzPXQpfSgidW5kZWZpbmVkIiE9dHlwZW9mIHdpbmRvdz93aW5kb3c6dGhpcyxkb2N1bWVudCk7" +echo -n "${HTML5SHIV_BASE64}" | ${BIN_BASE64} --decode > "${FOLDER}/html5shiv.min.js" +HTML5SHIV_BASE64= + +FOCUSFIX_BASE64="LyogWWV0IEFub3RoZXIgTXVsdGljb2x1bW4gTGF5b3V0IC0gaHR0cDovL3d3dy55YW1sLmRlICovCihmdW5jdGlvbigpe3ZhciBZQU1MX2ZvY3VzRml4PXtza2lwQ2xhc3M6J3ltLXNraXAnLGluaXQ6ZnVuY3Rpb24oKXt2YXIgdXNlckFnZW50PW5hdmlnYXRvci51c2VyQWdlbnQudG9Mb3dlckNhc2UoKTt2YXIgaXNfd2Via2l0PXVzZXJBZ2VudC5pbmRleE9mKCd3ZWJraXQnKT4tMTt2YXIgaXNfaWU9dXNlckFnZW50LmluZGV4T2YoJ21zaWUnKT4tMTtpZihpc193ZWJraXR8fGlzX2llKXt2YXIgYm9keT1kb2N1bWVudC5ib2R5LGhhbmRsZXI9WUFNTF9mb2N1c0ZpeC5jbGljaztpZihib2R5LmFkZEV2ZW50TGlzdGVuZXIpe2JvZHkuYWRkRXZlbnRMaXN0ZW5lcignY2xpY2snLGhhbmRsZXIsITEpfWVsc2UgaWYoYm9keS5hdHRhY2hFdmVudCl7Ym9keS5hdHRhY2hFdmVudCgnb25jbGljaycsaGFuZGxlcil9fX0sdHJpbTpmdW5jdGlvbihzdHIpe3JldHVybiBzdHIucmVwbGFjZSgvXlxzXHMqLywnJykucmVwbGFjZSgvXHNccyokLywnJyl9LGNsaWNrOmZ1bmN0aW9uKGUpe2U9ZXx8d2luZG93LmV2ZW50O3ZhciB0YXJnZXQ9ZS50YXJnZXR8fGUuc3JjRWxlbWVudDt2YXIgYT10YXJnZXQuY2xhc3NOYW1lLnNwbGl0KCcgJyk7Zm9yKHZhciBpPTA7aTxhLmxlbmd0aDtpKyspe3ZhciBjbHM9WUFNTF9mb2N1c0ZpeC50cmltKGFbaV0pO2lmKGNscz09PVlBTUxfZm9jdXNGaXguc2tpcENsYXNzKXtZQU1MX2ZvY3VzRml4LmZvY3VzKHRhcmdldCk7YnJlYWt9fX0sZm9jdXM6ZnVuY3Rpb24obGluayl7aWYobGluay5ocmVmKXt2YXIgaHJlZj1saW5rLmhyZWYsaWQ9aHJlZi5zdWJzdHIoaHJlZi5pbmRleE9mKCcjJykrMSksdGFyZ2V0PWRvY3VtZW50LmdldEVsZW1lbnRCeUlkKGlkKTtpZih0YXJnZXQpe3RhcmdldC5zZXRBdHRyaWJ1dGUoInRhYmluZGV4IiwiLTEiKTt0YXJnZXQuZm9jdXMoKX19fX07WUFNTF9mb2N1c0ZpeC5pbml0KCl9KSgp" +echo -n "${FOCUSFIX_BASE64}" | ${BIN_BASE64} --decode > "${FOLDER}/yaml-focusfix.min.js" +FOCUSFIX_BASE64= + +#------------------------------------------------------------------------------- +# Create robots.txt for later use on a public web server. +#------------------------------------------------------------------------------- +${BIN_CAT} < "${FOLDER}/robots.txt" +User-Agent: * +Disallow: / +EOF + +#------------------------------------------------------------------------------- +# Global header template for the simple template engine. +#------------------------------------------------------------------------------- +# zsh: readonly is not valid in this context: +HEADER=$( ${BIN_CAT} <<'EOF' + + + + + ${HEAD_TITLE} + + + + + + + +
+
+
+

${HEADER_H1}

+ ${HEADER_SUBTITLE} +
+ +
+EOF +) + +#------------------------------------------------------------------------------- +# Partial template for the case information for the simple template engine. +#------------------------------------------------------------------------------- +CASE_INFORMATION=$( ${BIN_CAT} <<'EOF' +

Case Information

+

+ + (Used commands: + date) + +

+ + + + + + + + + + + + + +
Case Number:${CASE_NUMBER}
Officer:${OFFICER}
Date:${DATE}
+EOF +) + +#------------------------------------------------------------------------------- +# Partial template for the image information for the simple template engine. +#------------------------------------------------------------------------------- +IMAGE_INFORMATION=$( ${BIN_CAT} <<'EOF' +

Details of the image file

+

+ + (Used commands: + img_stat, + stat and + openssl) + +

+ + + + + + + + + + + + + + + + + + + + + + + + + +
File Name:${IMAGE_FILE}
Image Type:${IMAGE_TYPE}
Size of File:${FILE_SIZE} bytes
Size of Data:${DATA_SIZE} bytes
MD5 of File:${MD5}
SHA1 of File:${SHA1}
+EOF +) + +#------------------------------------------------------------------------------- +# Partial template for the partition information for the simple template engine. +#------------------------------------------------------------------------------- +PARTITION_INFORMATION=$( ${BIN_CAT} <<'EOF' +

Partition layout of the volume system (partition tables)

+

+ + (Used command: + mmls + "${IMAGE_FILE}") + +

+

+ ${SCHEME} +
+ ${OFFSET} +
+ ${UNITS} +

+ + + + + + + + + + +${PARTITION_TABLE} +
#1)Slot2)Start3)End3)Length3)Description4)Extra5)
+

+ + 1) + ---: This is used to identify an entry where TSK was not able to find a partition table. +
+ 2) + ##: A two digit number is used with volume systems that have only one table and the number corresponds to the entry in the single table. +
+ ##:##: This format is used with volume systems that have multiple tables (like DOS partitions). The first two numbers correspond to the table ID and the second set of numbers correspond to the entry in that table. 00:01 is entry 1 in table 0. +
+ Meta: This is used to describe an entry that is created by TSK to show where metadata structures are located. Meta entries can be suppressed with flag options. These entries are not in any volume system table, but maybe helpful to the user. +
+ -----: This is used to identify an entry that is created by TSK for unallocated space. +
+ 3) + The Start, End, and Length columns describe the starting, ending and length of the volume (in sectors). +
+ 4) + -----: This is used to identify an entry where TSK was not able to find a partition id. +
+ 5) + -----: This is used to identify an entry where TSK was not able to find a file system. +
+

+EOF +) + +#------------------------------------------------------------------------------- +# Partial template for the filesystem metadata information +# for the simple template engine. +#------------------------------------------------------------------------------- +FSSTAT=$( ${BIN_CAT} <<'EOF' +

General details of the file system in partition ${cnt}

+

+ + (Used command: + fsstat + -o "${offset}" "${IMAGE_FILE}") + +

+
+${FSSTAT_OUTPUT}
+          
+EOF +) + +#------------------------------------------------------------------------------- +# Partial template for the file metadata information +# for the simple template engine. +#------------------------------------------------------------------------------- +ISTAT=$( ${BIN_CAT} <<'EOF' +

Details of the meta-data structure of a meta-data address

+

+ + (Used command: + istat + -o "${offset}" "${IMAGE_FILE}" "${meta_addr}") + +

+
+${istat_output}
+          
+EOF +) + +#------------------------------------------------------------------------------- +# Partial template for the filesystem listing +# for the simple template engine. +#------------------------------------------------------------------------------- +FLS=$( ${BIN_CAT} <<'EOF' +

Listing of file and directory names in partition ${cnt}

+

+ + (Used command: + fls + -o "${offset}" -r -p "${IMAGE_FILE}") + +

+ + + + + + + + +${FLS_TABLE} +
Type1)deletedMetadata addressNameExtra(s)2)
+

+ + 1) + Type as saved in the file's file name structure/type as saved in the file's metadata structure +
+ -: Unknown type, + r: Regular file, + d: Directory, + c: Character device, + b: Block device, + l: Symbolic link, + p: Named FIFO, + s: Shadow, + h: Socket, + w: Whiteout, + v: TSK Virtual file / directory (not a real directory, created by TSK for convenience) +
+ 2) + Commands used for identifying and extracting images: + icat + and + file +
+ -----: istat was not able to find some details of a meta-data structure. +
+

+EOF +) + +#------------------------------------------------------------------------------- +# Global footer template for the simple template engine. +#------------------------------------------------------------------------------- +FOOTER=$( ${BIN_CAT} <<'EOF' +
+ +
+
+ + + +EOF +) + +#------------------------------------------------------------------------------- +# "Controller" for the partial template for the partition information. +#------------------------------------------------------------------------------- +render_partition_table() { + cnt="001" + ${BIN_PRINTF} "%s\n" "${PARTITIONS_DATA}" | while read -r line ; do + # TSK <= 4.2.0: 00:00 or TSK >= 4.3.0: 000:000 + # (Maybe check for 4.3.0 or higher could be a cleaner solution?) + if ${BIN_PRINTF} "%s" "${line}" | ${BIN_GREP} --extended-regexp ".*\|([[:digit:]]{2,3}:)?[[:digit:]]{2,3}\|.*" > /dev/null 2>&1 ; then + + if [ "${DEBUG}" = "on" ] ; then + ${BIN_PRINTF} "line (mmls): %s\n" "${line}" 1>&2 + fi + + if [ -f "${FOLDER}/PART_${cnt}/fsstat.html" ] ; then + line="${line}|[fsstat]" + line="${line} [fls]" + LC_ALL=C cnt="$( ${BIN_PRINTF} "%03d" "$(( cnt + 1 ))" )" + else + line="${line}|-----" + fi + else + line="${line}|-----" + fi + OLDIFS=${IFS} + IFS="|" + ${BIN_PRINTF} " \n" + for value in ${line} ; do + ${BIN_PRINTF} " %s\n" "${value}" + done + ${BIN_PRINTF} " \n" + IFS=${OLDIFS} + done +} + +#------------------------------------------------------------------------------- +# "Controller" for the partial template for the file listing. +#------------------------------------------------------------------------------- +render_fls() { + echo "${FLS_OUTPUT}" | while read -r line ; do + # Because the behavior of the #, ##, %, and %% operators + # are unspecified by POSIX it is more portable to use sed. + meta_addr="$( ${BIN_PRINTF} "%s" "${line}" | ${BIN_SED} "${SED_EXT_REGEXP}" 's/(.*\|.*\|)([[:digit:]\-]+)(\|.*)/\2/' )" +#------------------------------------------------------------------------------- +# Generation of all istat html files. +#------------------------------------------------------------------------------- + istat_output="$( ${BIN_ISTAT} -o "${offset}" "${IMAGE_FILE}" "${meta_addr}" 2>/dev/null )" + if [ -n "${istat_output}" ] ; then + + if [ "${DEBUG}" = "on" ] ; then + ${BIN_PRINTF} "line (fls): %s " "${line}" 1>&2 + fi + + prefix="../../" + top_nav="$( ${BIN_CAT} <<'EOF' +
  • img_stat/mmls
  • +
  • fsstat
  • +
  • fls
  • +
  • istat
  • +EOF +)" + render_template "${HEADER}" > "${FOLDER}/PART_${cnt}/istat/${meta_addr}.html" + render_template "${ISTAT}" >> "${FOLDER}/PART_${cnt}/istat/${meta_addr}.html" + render_template "${FOOTER}" >> "${FOLDER}/PART_${cnt}/istat/${meta_addr}.html" + line="${line}|[istat]" +#------------------------------------------------------------------------------- +# Extraction of pictures. +#------------------------------------------------------------------------------- +# Using a shell variable as a buffer may safe time (less slow reading from disk) +# but is limited in size (see: "execve"). The limit seems to be the lowest in +# Linux + ksh93. In addition it seems that the limit depends on the available +# Memory. +# "My" solution is to first check the size from "istat" and use a shell variable +# up to a max size. For bigger files do an icat twice. +# Get the size should work for all by TSK supported filesystems, only tested with: +# HFS+ -> "Size:" +# Ext2/3/4 -> "size:" +# UFS2 -> "size:" +# FAT12/16/32: "Size:" +# NTFS -> "Allocated Size:" oder "Type $DATA...size:" +# (if more then one size were found, choose the bigger one.) + size="$( ${BIN_PRINTF} "%s" "${istat_output}" | ${BIN_SED} "${SED_EXT_REGEXP}" -n '/^([Ss]ize|Allocated Size|Type:[[:space:]]\$DATA.*size):/ s/^(([Ss]ize|Allocated Size|Type:[[:space:]]\$DATA.*size):[[:space:]])([[:digit:]]+)(.*)/\3/ p' | sort -n | tail -n 1 )" + # If size is empty fill with zero. + if [ -z "${size}" ] ; then + size="0" + fi + if [ "${size}" -lt "100000" ] ; then + if [ "${DEBUG}" = "on" ] ; then + ${BIN_PRINTF} "(size: %d => base64 buffering)\n" "${size}" 1>&2 + fi + base64_img="$( ${BIN_ICAT} -o "${offset}" "${IMAGE_FILE}" "${meta_addr}" 2>/dev/null | ${BIN_BASE64} )" + mime_type="$( echo -n "${base64_img}" | ${BIN_BASE64} --decode | ${BIN_FILE} --mime-type - )" + if ${BIN_PRINTF} "%s" "${mime_type}" | ${BIN_GREP} --extended-regexp ": image/" > /dev/null 2>&1 ; then + # "file" in macOS misdetects /$UpCase (NTFS) as an image. + if ! ${BIN_PRINTF} "%s" "${line}" | ${BIN_GREP} --fixed-strings '|/$UpCase|' > /dev/null 2>&1 ; then + if ! [ -d "${FOLDER}/PART_${cnt}/pictures" ] ; then + ${BIN_MKDIR} -p "${FOLDER}/PART_${cnt}/pictures" + fi + # This simple solution for file extensions doesn't work very well. + # ext="$( ${BIN_PRINTF} "%s" "${mime_type}" | ${BIN_SED} "${SED_EXT_REGEXP}" 's/(.*\/)(.*)/\2/' )" + # echo -n "${base64_img}" | ${BIN_BASE64} --decode > "${FOLDER}/PART_${cnt}/pictures/${meta_addr}.${ext}" + # line="${line} [Picture]" + echo -n "${base64_img}" | ${BIN_BASE64} --decode > "${FOLDER}/PART_${cnt}/pictures/${meta_addr}" + line="${line} [Picture]" + fi + fi + else + if [ "${DEBUG}" = "on" ] ; then + ${BIN_PRINTF} "(size: %d => double icating)\n" "${size}" 1>&2 + fi + mime_type="$( ${BIN_ICAT} -o "${offset}" "${IMAGE_FILE}" "${meta_addr}" 2>/dev/null | ${BIN_FILE} --mime-type - )" + if ${BIN_PRINTF} "%s" "${mime_type}" | ${BIN_GREP} --extended-regexp ": image/" > /dev/null 2>&1 ; then + if ! ${BIN_PRINTF} "%s" "${line}" | ${BIN_GREP} --fixed-strings '|/$UpCase|' > /dev/null 2>&1 ; then + if ! [ -d "${FOLDER}/PART_${cnt}/pictures" ] ; then + ${BIN_MKDIR} -p "${FOLDER}/PART_${cnt}/pictures" + fi + ${BIN_ICAT} -o "${offset}" "${IMAGE_FILE}" "${meta_addr}" 2>/dev/null > "${FOLDER}/PART_${cnt}/pictures/${meta_addr}" + line="${line} [Picture]" + fi + fi + fi + OLDIFS=${IFS} + IFS="|" + ${BIN_PRINTF} " \n" + for value in ${line} ; do + ${BIN_PRINTF} " %s\n" "${value}" + done + ${BIN_PRINTF} " \n" + IFS=${OLDIFS} + else + line="${line}|-----" + fi + done +} + +#------------------------------------------------------------------------------- +# "The template engine" +# (inspired by: http://pempek.net/articles/2013/07/08/bash-sh-as-template-engine/) +#------------------------------------------------------------------------------- +render_template() { + eval "echo \"${1}\"" +} + +#------------------------------------------------------------------------------- +# Variables as "controllers" for the simple template engine. +#------------------------------------------------------------------------------- +readonly HEAD_TITLE="The Sleuth Kit®" +readonly HEADER_H1="The Sleuth Kit®" +readonly HEADER_SUBTITLE="... featured by awk, file, grep, openssl, sed & co." + +#------------------------------------------------------------------------------- +# Generate case and image informations. +#------------------------------------------------------------------------------- +readonly DATE="$( ${BIN_DATE} )" +if [ "${DEBUG}" = "on" ] ; then + ${BIN_PRINTF} "DATE: %s\n" "${DATE}" 1>&2 +fi + +case "${OS_NAME}" in + Darwin|FreeBSD) readonly FILE_SIZE="$( ${BIN_STAT} -f "%z" "${IMAGE_FILE}" )" + ;; + Linux) readonly FILE_SIZE="$( ${BIN_STAT} -c "%s" "${IMAGE_FILE}" )" + ;; +esac +if [ "${DEBUG}" = "on" ] ; then + ${BIN_PRINTF} "FILE_SIZE: %s\n" "${FILE_SIZE}" 1>&2 +fi + +readonly DATA_SIZE="$( ${BIN_IMG_STAT} "${IMAGE_FILE}" | ${BIN_GREP} --extended-regexp 'Size.*in bytes:' | ${BIN_AWK} '{ print $NF; }' )" +if [ "${DEBUG}" = "on" ] ; then + ${BIN_PRINTF} "DATA_SIZE: %s\n" "${DATA_SIZE}" 1>&2 +fi + +readonly IMAGE_TYPE="$( ${BIN_IMG_STAT} "${IMAGE_FILE}" | ${BIN_GREP} --fixed-strings 'Image Type:' | ${BIN_AWK} '{ print $NF; }' )" +if [ "${DEBUG}" = "on" ] ; then + ${BIN_PRINTF} "IMAGE_TYPE: %s\n" "${IMAGE_TYPE}" 1>&2 +fi + +readonly MD5="$( ${BIN_OPENSSL} dgst -md5 "${IMAGE_FILE}" | ${BIN_AWK} '{ print $NF; }' )" +if [ "${DEBUG}" = "on" ] ; then + ${BIN_PRINTF} "MD5: %s\n" "${MD5}" 1>&2 +fi + +readonly SHA1="$( ${BIN_OPENSSL} dgst -SHA1 "${IMAGE_FILE}" | ${BIN_AWK} '{ print $NF; }' )" +if [ "${DEBUG}" = "on" ] ; then + ${BIN_PRINTF} "SHA1: %s\n" "${SHA1}" 1>&2 +fi + +#------------------------------------------------------------------------------- +# Generate partition informations. +#------------------------------------------------------------------------------- +readonly MMLS="$( ${BIN_MMLS} "${IMAGE_FILE}" 2>/dev/null )" + +# Filesystem in a partition +if [ -n "${MMLS}" ] ; then + readonly SCHEME="$( ${BIN_PRINTF} "%s" "${MMLS}" | ${BIN_SED} -n "1p" )" + readonly OFFSET="$( ${BIN_PRINTF} "%s" "${MMLS}" | ${BIN_SED} -n "2p" )" + readonly UNITS="$( ${BIN_PRINTF} "%s" "${MMLS}" | ${BIN_SED} -n "3p" )" + readonly PARTITIONS_DATA="$( ${BIN_PRINTF} "%s" "${MMLS}" \ + | ${BIN_GREP} --extended-regexp "^[[:digit:]]" \ + | ${BIN_AWK} 'BEGIN{ OFS="|"; CNT=1; } { description = substr( $0, index( $0, $6 ) ); gsub( /\|/, " ", description ); print CNT++, $2, $3, $4, $5, description }' )" +# Filesystem (or whatever) without a partition +else + readonly SCHEME="No partition type found" + readonly OFFSET="Offset Sector: 0" + readonly UNITS="Units are in 512-byte sectors" + readonly LENGTH="$( LC_ALL="C" ${BIN_PRINTF} "%010d" "$(( ${DATA_SIZE} / 512 ))" )" + readonly END="$( LC_ALL="C" ${BIN_PRINTF} "%010d" "$(( ${DATA_SIZE} / 512 - 1 ))" )" + if [ "${DEBUG}" = "on" ] ; then + ${BIN_PRINTF} "LENGTH: %s\n" "${LENGTH}" 1>&2 + ${BIN_PRINTF} "END: %s\n" "${END}" 1>&2 + fi + readonly PARTITIONS_DATA="---|000:000|0000000000|${END}|${LENGTH}|-----" +fi + +# Because it could be 128 partitions at maximum we need a three character long number. +cnt="001" +# 1. TSK <= 4.2.0: 00:00 or TSK >= 4.3.0: 000:000 +# 2. "plain" awk in FreeBSD11 should but doesn't know {m,n} +for offset in $( ${BIN_PRINTF} "%s" "${PARTITIONS_DATA}" | ${BIN_AWK} -F "|" '$2 ~ /([[:digit:]][[:digit:]][[:digit:]]?:)?[[:digit:]][[:digit:]][[:digit:]]?/ { print $3; }' ) ; do + if ! [ -d "${FOLDER}/PART_${cnt}/istat" ] ; then + ${BIN_MKDIR} -p "${FOLDER}/PART_${cnt}/istat" + if [ "${cnt}" -le "100" ] ; then + lnscnt="$( ${BIN_PRINTF} "%s" "${cnt}" | ${BIN_SED} "${SED_EXT_REGEXP}" 's/^([[:digit:]]?)([[:digit:]]{2})/\2/' )" + # Add symlinks with two digets for Fergus. ;-) + if ! [ -L "${FOLDER}/PART_${lnscnt}" ] ; then + cd "${FOLDER}" + ${BIN_LN} -s "PART_${cnt}" "PART_${lnscnt}" + cd .. + fi + fi + fi +#------------------------------------------------------------------------------- +# Generate filesystem metadata informations. +#------------------------------------------------------------------------------- + FSSTAT_OUTPUT="$( ${BIN_FSSTAT} -o "${offset}" "${IMAGE_FILE}" 2>/dev/null )" + if [ -n "${FSSTAT_OUTPUT}" ] ; then + prefix="../" + top_nav="$( ${BIN_CAT} <<'EOF' +
  • img_stat/mmls
  • +
  • fsstat
  • +
  • fls
  • +EOF +)" + render_template "${HEADER}" > "${FOLDER}/PART_${cnt}/fsstat.html" + render_template "${FSSTAT}" >> "${FOLDER}/PART_${cnt}/fsstat.html" + render_template "${FOOTER}" >> "${FOLDER}/PART_${cnt}/fsstat.html" + fi +#------------------------------------------------------------------------------- +# Generate file listing. +#------------------------------------------------------------------------------- + FLS_OUTPUT="$( ${BIN_FLS} -o "${offset}" -r -p "${IMAGE_FILE}" 2>/dev/null \ + | ${BIN_AWK} 'BEGIN{ OFS="|"; } { if ( $2 == "*" ) { sub( /:$/, "", $3 ); filename = substr( $0, index( $0, $4 ) ); gsub( /\|/, " ", filename ); print $1, "x", $3, "/" filename; } else { sub( /:$/, "", $2 ); filename = substr( $0, index( $0, $3 ) ); gsub( /\|/, " ", filename ); print $1, " ", $2, "/" filename; } }' )" + if [ -n "${FLS_OUTPUT}" ] ; then + prefix="../" + top_nav="$( ${BIN_CAT} <<'EOF' +
  • img_stat/mmls
  • +
  • fsstat
  • +
  • fls
  • +EOF +)" + render_template "${HEADER}" > "${FOLDER}/PART_${cnt}/fls.html" + FLS_TABLE="$( render_fls )" + render_template "${FLS}" >> "${FOLDER}/PART_${cnt}/fls.html" + render_template "${FOOTER}" >> "${FOLDER}/PART_${cnt}/fls.html" + fi + LC_ALL=C cnt="$( ${BIN_PRINTF} "%03d" "$(( cnt + 1 ))" )" +done + +#------------------------------------------------------------------------------- +# Generate main html file. +#------------------------------------------------------------------------------- +prefix="" +top_nav="$( ${BIN_CAT} <<'EOF' +
  • img_stat/mmls
  • +EOF +)" +render_template "${HEADER}" > "${FOLDER}/main.html" +render_template "${CASE_INFORMATION}" >> "${FOLDER}/main.html" +render_template "${IMAGE_INFORMATION}" >> "${FOLDER}/main.html" +PARTITION_TABLE="$( render_partition_table )" >> "${FOLDER}/main.html" +render_template "${PARTITION_INFORMATION}" >> "${FOLDER}/main.html" +render_template "${FOOTER}" >> "${FOLDER}/main.html" + +#------------------------------------------------------------------------------- +# Open main html file in a browser. +#------------------------------------------------------------------------------- +case "${OS_NAME}" in + Darwin) ${BIN_OPEN} -a "${BROWSER}" "${FOLDER}/main.html" + ;; + Linux|FreeBSD) ${BROWSER} "${FOLDER}/main.html" + ;; +esac + +exit 0