|
Server : Apache System : Linux s1230 5.15.0-139-generic #149~20.04.1 SMP Tue Jul 14 11:21:49 UTC 2026 x86_64 User : p141464 ( 418825) PHP Version : 7.4.33.12 Disable Function : NONE Directory : /usr/local/bin/ |
Upload File : |
#!/bin/bash
SCRIPT_VERSION='1.0.1'
BY='@andrej'
# help
function usage() {
echo "TYPO3 update checker v${SCRIPT_VERSION}"
echo
echo "Usage: ${0} [OPTIONS]"
echo "Options:"
echo " -h --help This help message"
echo
echo " -i --no-print-inactive Disable printing of inactive extensions"
echo " -j --json Print as JSON"
echo " -m --no-print-missing Disable printing of extensions without defined TYPO3 dependency"
echo " -p --installation-path (required) Installation path of TYPO3 CMS (like /home/www/p1337/html/typo3/)"
echo " -t --target-version (required) Check extension compatibility against this TYPO3 version (like 12.4)"
echo " -v --version Print version"
exit 1
}
# get the cli options
[[ "${#}" -le 0 ]] && { echo "missing required arguments"; usage; }
OPTIONS=$(getopt -o hvijmp:t: --long help,version,no-print-inactive,json,no-print-missing,installation-path:,target-version: -- "${@}")
[[ "${?}" -ne 0 ]] && { usage; }
eval set -- "${OPTIONS}"
# set defaults
TYPO3_INSTALL_PATH=""
TYPO3_TARGET_VERSION=""
PRINT_AS_JSON="${PRINT_AS_JSON:-off}" # default off
NO_PRINT_INACTIVE="${NO_PRINT_INACTIVE:-off}" # default off
NO_PRINT_MISSING_DEPENDENCY="${NO_PRINT_MISSING_DEPENDENCY:-off}" # default off
while true; do
case ${1} in
-h | --help) usage
shift
;;
-i | --no-print-inactive) NO_PRINT_INACTIVE="on"
shift
;;
-j | --json) PRINT_AS_JSON="on"
shift
;;
-m | --no-print-missing) NO_PRINT_MISSING_DEPENDENCY="on"
shift
;;
-p | --installation-path) TYPO3_INSTALL_PATH="${2%/}" # docroot like /home/www/{{PROJECT}}/html/typo3 or /html/typo3
shift 2
;;
-t | --target-version) TYPO3_TARGET_VERSION="$( cut -d'.' -f1-2 <<< ${2} )" # MAJOR + MINOR (PATCH level will be cutoff)
shift 2
;;
-v | --version) echo "${SCRIPT_VERSION}" && exit 0
;;
--) shift
break
;;
*) break
;;
esac
done
[[ -z "${TYPO3_INSTALL_PATH}" ]] || [[ -z "${TYPO3_TARGET_VERSION}" ]] && { echo "missing required arguments"; usage; }
if [[ ! "${TYPO3_INSTALL_PATH}" =~ ^(/home/www/p.*)?/html/.* ]] && [[ ! -d "${TYPO3_INSTALL_PATH}" ]]; then
echo "wrong installation path: ${TYPO3_INSTALL_PATH}"
usage
fi
TYPO3_EXTENSION_PATH="${TYPO3_INSTALL_PATH}/typo3conf/ext"
PACKAGESTATE_FILE="${TYPO3_INSTALL_PATH}/typo3conf/PackageStates.php"
# check activation state of an extension
function check_extension_activation_state() {
local EXT_NAME="${1}"
ACTIVATION_STATE="$( sed -rne 's/\r$//' -e 's/\t//g' -e "\@^\ *'${EXT_NAME}'@,\@packagePath@{\@packagePath@{s/packagePath//;s/['=>, ]//gp}}" ${PACKAGESTATE_FILE} )"
if [[ -n "${ACTIVATION_STATE}" ]]; then
# active when ACTIVATION_STATE is not null
echo "active"
else
echo "inactive"
fi
}
# check compatibility of extension agains typo3 target version
function check_extension_compatibility() {
local EXTENSION_MAX_COMPAT_VERSION="$( cut -d'.' -f1-2 <<< ${1#*\-} )" # if it's a version range, get 2nd part after dash, else the remaining (like "9.5")
local EXTENSION_MIN_COMPAT_VERSION="$( cut -d'.' -f1-2 <<< ${1%\-*} )" # if it's a version range, get 1st part before dash, else the remaining (like "9.5")
# if EXTENSION_MAX_COMPAT_VERSION matched a string or is empty, assign value 0
if [[ "${EXTENSION_MAX_COMPAT_VERSION}" =~ [a-zA-Z] ]] || [[ -z "${EXTENSION_MAX_COMPAT_VERSION}" ]]; then
EXTENSION_MAX_COMPAT_VERSION="0"
fi
# if EXTENSION_MIN_COMPAT_VERSION matched a string or is empty, assign value 0
if [[ "${EXTENSION_MIN_COMPAT_VERSION}" =~ [a-zA-Z] ]] || [[ -z "${EXTENSION_MIN_COMPAT_VERSION}" ]]; then
EXTENSION_MIN_COMPAT_VERSION="0"
fi
# EXTENSION_MAX_COMPAT_VERSION must be greater than or equal to TYPO3_TARGET_VERSION & EXTENSION_MIN_COMPAT_VERSION
# EXTENSION_MAX_COMPAT_VERSION cannot be 0
# EXTENSION_MIN_COMPAT_VERSION must be smaller than or equal to TYPO3_TARGET_VERSION
if [[ $( echo "scale=1;${EXTENSION_MAX_COMPAT_VERSION} > ${EXTENSION_MIN_COMPAT_VERSION}" | bc -lq ) == 1 || ${EXTENSION_MAX_COMPAT_VERSION} == ${EXTENSION_MIN_COMPAT_VERSION} ]] && \
[[ ${EXTENSION_MAX_COMPAT_VERSION} != 0 ]] && \
[[ $(echo "scale=1;${EXTENSION_MIN_COMPAT_VERSION} < ${TYPO3_TARGET_VERSION}" | bc -lq ) == 1 || ${EXTENSION_MIN_COMPAT_VERSION} == ${TYPO3_TARGET_VERSION} ]] && \
[[ $(echo "scale=1;${EXTENSION_MAX_COMPAT_VERSION} > ${TYPO3_TARGET_VERSION}" | bc -lq ) == 1 || ${EXTENSION_MAX_COMPAT_VERSION} == ${TYPO3_TARGET_VERSION} ]]; then
echo "compatible"
else
echo "incompatible"
fi
}
##################
# JSON functions #
##################
function out() {
echo -n "${@}"
}
function new_array() {
out '['
}
function close_array() {
out ']'
}
function new_object() {
out '{'
}
function close_object() {
out '}'
}
function add_key() {
out "\"${@}\":"
}
function add_value() {
out "\"${@}\""
}
function add_key_value_pair() {
out "\"${1}\":\"${2}\""
}
function comma() {
out ","
}
function prepend_comma() {
if [[ "${NEXT_OBJECT_MUST_PREPEND_COMMA}" == "True" ]]; then
comma
unset NEXT_OBJECT_MUST_PREPEND_COMMA
fi
}
function print_title_by_condition() {
if [[ "${PRINT_AS_JSON}" == "on" ]]; then
prepend_comma
new_object
add_key_value_pair "title" "${TITLE}"
comma
add_key_value_pair "description" "${DESCRIPTION}"
comma
add_key "extensions"
new_array
else
echo "### ${TITLE}"
echo "${DESCRIPTION}:"
echo ''
fi
}
PRINT_TITLE_GEN=true
PRINT_TITLE_INA=true
PRINT_TITLE_DEP=true
function print_title_general() {
if [[ ${PRINT_TITLE_GEN} == true ]]; then
local TITLE="Inkompatible Extensions"
local DESCRIPTION="Die folgenden Extensions sind laut Angabe der Entwickler*innen nicht mit TYPO3 ${TYPO3_TARGET_VERSION} kompatibel"
print_title_by_condition
fi
PRINT_TITLE_GEN=false
}
function print_title_inactive() {
if [[ ${PRINT_TITLE_INA} == true ]]; then
local TITLE="Deaktivierte Extensions"
local DESCRIPTION="Auch wenn die folgenden Extensions inaktiv sind, könnten sie beim Update auf TYPO3 ${TYPO3_TARGET_VERSION} Probleme verursachen, da sie laut Angabe der Entwickler*innen nicht kompatibel sind"
print_title_by_condition
fi
PRINT_TITLE_INA=false
}
function print_title_dependency() {
if [[ ${PRINT_TITLE_DEP} == true ]]; then
local TITLE="Extensions ohne Abhängigkeit zu TYPO3"
local DESCRIPTION="Für die folgenden Extensions wurde keine spezifische Version für TYPO3 von den Entwickler*innen festgelegt, daher ist es wahrscheinlich, dass sie nicht mit TYPO3 ${TYPO3_TARGET_VERSION} kompatibel sind"
print_title_by_condition
fi
PRINT_TITLE_DEP=false
}
# print extensions as JSON object, or unformatted
function print_extension() {
if [[ "${PRINT_AS_JSON}" == "on" ]]; then
new_object
add_key_value_pair "name" "${1}"
comma
add_key_value_pair "version" "${2}"
close_object
else
echo "- ${1} (v${2})"
fi
}
# do not print these extensions in a loop
function check_ignore_extension() {
local EXT_NAME="${1}"
local EXT_TO_IGNORE=(typo3_console)
for EXT in ${EXT_TO_IGNORE[@]}; do
if [[ "${EXT}" == "${EXT_NAME}" ]]; then
echo 'continue'
fi
done
}
# get typo3 extensions and versions
function find_extensions() {
local EXT_CONF_FILES
local EXT_VERSIONS
local EXT_DEPENDENCIES
local PRINT_TYPO3_DEPENDENCY
# get extension configuration files
EXT_CONF_FILES=()
for CONF in $( find ${TYPO3_EXTENSION_PATH}/ -maxdepth 2 -type f -name 'ext_emconf.php' ); do
if [[ -n "${CONF}" ]]; then
EXT_CONF_FILES+=("${CONF}") # full path to ext_emconf.php
fi
done
# get extension versions
EXT_VERSIONS=()
for FILE in "${EXT_CONF_FILES[@]}"; do
FILE=${FILE%$'\r'} # remove carriage return "\r"
VERSION="$( sed -nre 's/\r$//' -e 's/\t//g' -e "/'version'\ /{/[0-9]/s/[\"'=>, version]//g;s/([0-9\.]{1,}).*/\1/gp}" ${FILE} )"
EXT_VERSIONS+=("${VERSION:-0}") # default value 0
done
# get extension dependency versions of typo3
EXT_DEPENDENCIES=()
for FILE in "${EXT_CONF_FILES[@]}"; do
FILE=${FILE%$'\r'} # remove carriage return "\r"
DEPENDS="$( sed -rne 's/\r$//' -e 's/\t//g' -e "/depends/,/typo3|cms-core/{/typo3|cms-core\>/{s/typo3|cms-core//;s/['=>, \*]//gp}}" ${FILE} )"
EXT_DEPENDENCIES+=("${DEPENDS:-0}") # default value 0
done
#################################
# print incompatible extensions #
#################################
EXTENSION_ARRAY=()
for ((i=0; i<${#EXT_CONF_FILES[@]}; i++)); do
EXTENSION_NAME="$( echo ${EXT_CONF_FILES[${i}]%$'\r'} | grep -o 'typo3conf/ext/.*/' | cut -d'/' -f3 )"
EXTENSION_VERSION="${EXT_VERSIONS[${i}]%$'\r'}"
EXTENSION_DEPENDENCY="${EXT_DEPENDENCIES[${i}]%$'\r'}"
EXTENSION_ACTIVATION_STATE="$( check_extension_activation_state "${EXTENSION_NAME}" )"
if [[ $( check_ignore_extension "${EXTENSION_NAME}" ) == 'continue' ]]; then
continue
fi
RESULT="$( check_extension_compatibility "${EXTENSION_DEPENDENCY}" )"
if [[ "${RESULT}" == "incompatible" ]]; then
if [[ "${EXTENSION_ACTIVATION_STATE}" == "inactive" ]]; then
continue # skip all inactive extensions
fi
if [[ ${EXTENSION_DEPENDENCY} == 0 ]]; then
continue # skip all extensions with missing TYPO3 dependency
fi
IFS=$'\n'
EXTENSION_ARRAY+=($(print_extension "${EXTENSION_NAME}" "${EXTENSION_VERSION}"))
fi
done
if [[ ${#EXTENSION_ARRAY[@]} > 0 ]]; then
print_title_general
if [[ "${PRINT_AS_JSON}" == "on" ]]; then
for ((elem=0; elem<${#EXTENSION_ARRAY[@]}; elem++)); do
echo -n "${EXTENSION_ARRAY[${elem}]}"
# add a comma as long elem isn't the last element of EXTENSION_ARRAY
if [[ ${elem} != $((${#EXTENSION_ARRAY[@]} - 1)) ]]; then
comma
fi
done
close_array
close_object
NEXT_OBJECT_MUST_PREPEND_COMMA=True
else
for ((elem=0; elem<${#EXTENSION_ARRAY[@]}; elem++)); do
echo "${EXTENSION_ARRAY[${elem}]}"
done
echo
fi
fi
#############################
# print inactive extensions #
#############################
#INACTIVE_COUNT=0
EXTENSION_ARRAY=()
for ((i=0; i<${#EXT_CONF_FILES[@]}; i++)); do
EXTENSION_NAME="$( echo ${EXT_CONF_FILES[${i}]%$'\r'} | grep -o 'typo3conf/ext/.*/' | cut -d'/' -f3 )"
EXTENSION_VERSION="${EXT_VERSIONS[${i}]%$'\r'}"
EXTENSION_DEPENDENCY="${EXT_DEPENDENCIES[${i}]%$'\r'}"
EXTENSION_ACTIVATION_STATE="$( check_extension_activation_state "${EXTENSION_NAME}" )"
if [[ $( check_ignore_extension "${EXTENSION_NAME}" ) == 'continue' ]]; then
continue
fi
RESULT="$( check_extension_compatibility "${EXTENSION_DEPENDENCY}" )"
if [[ "${RESULT}" == "incompatible" ]]; then
if [[ ${NO_PRINT_MISSING_DEPENDENCY} == 'on' && ${EXTENSION_DEPENDENCY} == 0 ]]; then
continue # skip extensions with missing TYPO3 dependency
fi
if [[ "${NO_PRINT_INACTIVE}" == 'on' && "${EXTENSION_ACTIVATION_STATE}" == "inactive" ]]; then
continue # skip inactive extensions
elif [[ "${NO_PRINT_INACTIVE}" == 'off' && "${EXTENSION_ACTIVATION_STATE}" == "inactive" ]]; then
IFS=$'\n'
EXTENSION_ARRAY+=($(print_extension "${EXTENSION_NAME}" "${EXTENSION_VERSION}"))
fi
fi
done
if [[ ${#EXTENSION_ARRAY[@]} > 0 ]]; then
print_title_inactive
if [[ "${PRINT_AS_JSON}" == "on" ]]; then
for ((elem=0; elem<${#EXTENSION_ARRAY[@]}; elem++)); do
echo -n "${EXTENSION_ARRAY[${elem}]}"
# add a comma as long elem isn't the last element of EXTENSION_ARRAY
if [[ ${elem} != $((${#EXTENSION_ARRAY[@]} - 1)) ]]; then
comma
fi
done
close_array
close_object
NEXT_OBJECT_MUST_PREPEND_COMMA=True
else
for ((elem=0; elem<${#EXTENSION_ARRAY[@]}; elem++)); do
echo "${EXTENSION_ARRAY[${elem}]}"
done
echo
fi
fi
##############################################
# print extensions with missing dependencies #
##############################################
EXTENSION_ARRAY=()
for ((i=0; i<${#EXT_CONF_FILES[@]}; i++)); do
EXTENSION_NAME="$( echo ${EXT_CONF_FILES[${i}]%$'\r'} | grep -o 'typo3conf/ext/.*/' | cut -d'/' -f3 )"
EXTENSION_VERSION="${EXT_VERSIONS[${i}]%$'\r'}"
EXTENSION_DEPENDENCY="${EXT_DEPENDENCIES[${i}]%$'\r'}"
EXTENSION_ACTIVATION_STATE="$( check_extension_activation_state "${EXTENSION_NAME}" )"
if [[ $( check_ignore_extension "${EXTENSION_NAME}" ) == 'continue' ]]; then
continue
fi
RESULT="$( check_extension_compatibility "${EXTENSION_DEPENDENCY}" )"
if [[ "${RESULT}" == "incompatible" ]]; then
if [[ "${NO_PRINT_INACTIVE}" == 'on' && "${EXTENSION_ACTIVATION_STATE}" == "inactive" ]]; then
continue # skip inactive extensions
fi
if [[ ${NO_PRINT_MISSING_DEPENDENCY} == 'on' && ${EXTENSION_DEPENDENCY} == 0 ]]; then
continue # skip extensions with missing TYPO3 dependency
elif [[ ${NO_PRINT_MISSING_DEPENDENCY} == 'off' && ${EXTENSION_DEPENDENCY} == 0 ]]; then
IFS=$'\n'
EXTENSION_ARRAY+=($(print_extension "${EXTENSION_NAME}" "${EXTENSION_VERSION}"))
fi
fi
done
if [[ ${#EXTENSION_ARRAY[@]} > 0 ]]; then
print_title_dependency
if [[ "${PRINT_AS_JSON}" == "on" ]]; then
for ((elem=0; elem<${#EXTENSION_ARRAY[@]}; elem++)); do
echo -n "${EXTENSION_ARRAY[${elem}]}"
# add a comma as long elem isn't the last element of EXTENSION_ARRAY
if [[ ${elem} != $((${#EXTENSION_ARRAY[@]} - 1)) ]]; then
comma
fi
done
close_array
close_object
# end: no comma
else
for ((elem=0; elem<${#EXTENSION_ARRAY[@]}; elem++)); do
echo "${EXTENSION_ARRAY[${elem}]}"
done
fi
fi
}
if [[ "${PRINT_AS_JSON}" == "on" ]]; then
# wrap a json array around the output
new_array
find_extensions # execute script
close_array
else
find_extensions # execute script
echo ''
fi