################################################################################
#
# httpd.cygclass - functions for building Apache HTTP Server mod_* modules
#
# Part of cygport - Cygwin packaging application
# Copyright (C) 2006-2020 Cygport authors
# Provided by the Cygwin project <https://cygwin.com/>
#
# cygport 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.
#
# cygport 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 cygport.  If not, see <https://www.gnu.org/licenses/>.
#
################################################################################

#****h* Cygclasses/httpd.cygclass
#  SYNOPSIS
#  inherit httpd
#  DESCRIPTION
#  The Apache Web Server is an HTTP server which can be extended through
#  plugins, known as DSOs, to support all sorts of tasks, scripting languages,
#  and more.  DSOs use the ".so" extension, even on platforms which use DLLs.
#
#  The purpose of httpd.cygclass is to provide functions and definitions
#  for building DSOs for the Cygwin Apache HTTP Server packages.  Cygwin packages
#  doing so should use the "httpd-" prefix before the canonical package name.
#  Because there is no consistent DSO source buildsystem, src_compile and
#  src_install must be defined yourself.
#  EXAMPLES
#  Apache module source packages do not have a single system.  Some packages
#  are autoconf-based:
#    inherit httpd
#    
#    NAME="httpd-mod_clamav"
#    VERSION=0.23
#    RELEASE=1
#    CATEGORY="Web"
#    SUMMARY="ClamAV filter module for Apache HTTP Server"
#    DESCRIPTION="mod_clamav is an Apache HTTP Server filter which scans the content
#    delivered by the proxy module (mod_proxy) for viruses using the Clamav
#    virus scanning engine."
#    HOMEPAGE="http://software.othello.ch/mod_clamav/"
#    LICENSE="GPL-2.0-only"
#    SRC_URI="http://software.othello.ch/mod_clamav/mod_clamav-${VERSION}.tar.gz"
#    SRC_DIR="mod_clamav-${VERSION}"
#    PATCH_URI="0.22-cygwin-layout.patch"
#    
#    src_compile() {
#      cd ${S}
#      cygautoreconf
#      cd ${B}
#      httpd_mod_compile
#    }
#    
#    src_install() {
#      cd ${B}
#      dohttpdmod mod_clamav
#      dohttpdconf ${S}/sample.conf ${S}/safepatterns.conf
#    }
#
#  Other simple module just ship the sources without a build system:
#
#    inherit httpd
#    
#    NAME="httpd-mod_geoip"
#    VERSION=1.2.8
#    RELEASE=1
#    CATEGORY="Web"
#    SUMMARY="Apache HTTP Server GeoIP module"
#    DESCRIPTION="mod_geoip2 is an Apache HTTP Server module for finding the country and
#    city that a web request originated from.  It uses the GeoIP library and
#    database to perform the lookup."
#    HOMEPAGE="https://dev.maxmind.com/geoip/legacy/mod_geoip2/"
#    LICENSE="Apache-1.1"
#    SRC_URI="https://github.com/maxmind/geoip-api-mod_geoip2/archive/v${VERSION}.tar.gz"
#    SRC_DIR="geoip-api-mod_geoip2-${VERSION}"
#    
#    src_compile() {
#      lndirs
#      cd ${B}
#      httpd_apxs_compile *.c -lGeoIP
#    }
#    
#    src_install() {
#      cd ${B}
#      dohttpdmod mod_geoip.la
#      httpd_loadmodules
#      dodoc README.php
#    }
#
#  REQUIRES
#  httpd-devel, libapr1-devel, libaprutil1-devel
#  SEE ALSO
#  mirror_apache
#****

# cross-compiling is not (yet?) supported
__cross_compiling_error

case ${PN} in httpd-mod_*)
ORIG_PN=${ORIG_PN:-${PN#httpd-}}
ORIG_P=${ORIG_PN}-${PV}
#****o* httpd.cygclass/CATEGORY (httpd)
#  DEFINITION
CATEGORY="Web"
#****
#****o* httpd.cygclass/SUMMARY (httpd)
#  DEFINITION
SUMMARY="Apache HTTP Server ${PN#httpd-mod_} module"
#****
;;
esac
HTTPD_MOD_NAME=${HTTPD_MOD_NAME:-${PN#httpd-}}

#****d* httpd.cygclass/HTTPD_APXS
#  DESCRIPTION
#  Path to apxs(1), the APache eXtenSion tool.
#****
HTTPD_APXS=/usr/bin/apxs

check_prog_req ${HTTPD_APXS} httpd-devel

#****d* httpd.cygclass/HTTPD
#  DESCRIPTION
#  Path to the Apache HTTP Server.
#****
HTTPD=/usr/sbin/httpd

#****d* httpd.cygclass/HTTPD_VERSION
#  DESCRIPTION
#  Full version of the Apache HTTP Server.
#****
HTTPD_VERSION=$(${HTTPD} -v | cut -d ' ' -f 3 | cut -d / -f 2)

#****d* httpd.cygclass/HTTPD_INCLUDEDIR
#  DESCRIPTION
#  Location of Apache HTTP Server headers.
#****
HTTPD_INCLUDEDIR="$(${HTTPD_APXS} -q INCLUDEDIR 2>/dev/null)"  # /usr/include/httpd

#****d* httpd.cygclass/HTTPD_LIBEXECDIR
#  DESCRIPTION
#  Installation path for Apache HTTP Server DSOs.
#****
HTTPD_LIBEXECDIR="$(${HTTPD_APXS} -q LIBEXECDIR 2>/dev/null)"  # /usr/lib/httpd/modules

#****d* httpd.cygclass/HTTPD_SYSCONFDIR
#  DESCRIPTION
#  Installation path for Apache HTTP Server configuration files.
#****
HTTPD_SYSCONFDIR="$(${HTTPD_APXS} -q SYSCONFDIR 2>/dev/null).d"  # /etc/httpd/conf.d

#****d* httpd.cygclass/HTTPD_SYSCONFMODULESDIR
#  DESCRIPTION
#  Installation path for Apache HTTP Server LoadModule directives
#****
HTTPD_SYSCONFMODULESDIR="$(${HTTPD_APXS} -q SYSCONFDIR 2>/dev/null).modules.d"  # /etc/httpd/conf.modules.d

#****d* httpd.cygclass/HTTPD_CFLAGS
#  DESCRIPTION
#  Compile flags for building Apache HTTP Server DSOs.
#****
HTTPD_CFLAGS="-I${HTTPD_INCLUDEDIR} $(${HTTPD_APXS} -q CFLAGS 2>/dev/null)"

#****d* httpd.cygclass/HTTPD_LIBS
#  DESCRIPTION
#  Link flags for building Apache HTTP Server DSOs.
#  NOTE
#  This is Cygwin specific due to the linking requirements of PE/COFF DLLs.
#****
HTTPD_LIBS="-lhttpd"

DEPS_PATH="${DEPS_PATH}${DEPS_PATH+:}/usr/sbin:${HTTPD_LIBEXECDIR}"

#****d* httpd.cygclass/APR_VERSION
#  DESCRIPTION
#  Major version of APR libraries used by the Apache HTTP Server.
#****
case ${HTTPD_VERSION:0:3} in
2.4)	APR_VERSION=1 ;;
*)
	if [ ! ${__cygport_check_prog_req_nonfatal} ]
	then
		error "Don't know anything about Apache HTTP Server ${HTTPD_VERSION}"
	fi
	;;
esac

#****d* httpd.cygclass/APR_CONFIG
#  DESCRIPTION
#  Path to matching APR_VERSION-specific apr-config script
#****

#****d* httpd.cygclass/APU_CONFIG
#  DESCRIPTION
#  Path to matching APR_VERSION-specific apu-config script
#****

case ${APR_VERSION} in
1)	APR_CONFIG=/usr/bin/apr-${APR_VERSION}-config
	APU_CONFIG=/usr/bin/apu-${APR_VERSION}-config
	;;
*)
	if [ ! ${__cygport_check_prog_req_nonfatal} ]
	then
		error "Illegal value ${APR_VERSION} for APR_VERSION"
	fi
	;;
esac

check_prog_req ${APR_CONFIG##*/} libapr${APR_VERSION}-devel
check_prog_req ${APU_CONFIG##*/} libaprutil${APR_VERSION}-devel

#****d* httpd.cygclass/APR_CFLAGS
#  DESCRIPTION
#  Compile flags for building against APR libraries
#****
APR_CFLAGS="$(${APU_CONFIG} --includes) $(${APR_CONFIG} --cppflags --includes)"

#****d* httpd.cygclass/APR_LIBS
#  DESCRIPTION
#  Link flags for building against APR libraries
#****
APR_LIBS="$(${APU_CONFIG} --link-ld) $(${APR_CONFIG} --link-ld --libs)"

#****d* httpd.cygclass/APR_LIBTOOL
#  DESCRIPTION
#  Path to libtool script used by APR-dependent packages
#****
APR_LIBTOOL="$(${APR_CONFIG} --apr-libtool)"

# Make HTTPD_* contain all required flags
HTTPD_CFLAGS+=" ${APR_CFLAGS}"
HTTPD_LIBS+=" ${APR_LIBS}"

if check_prog apreq2-config
then

#****d* httpd.cygclass/APREQ2_CONFIG
#  DESCRIPTION
#  Path to apreq2-config script
#****
APREQ2_CONFIG=/usr/bin/apreq2-config

#****d* httpd.cygclass/APREQ2_CFLAGS
#  DESCRIPTION
#  Compile flags for building against libapreq2
#  REQUIRES
#  libapreq2-devel
#****
APREQ2_CFLAGS="$(${APREQ2_CONFIG} --includes)"

#****d* httpd.cygclass/APREQ2_LIBS
#  DESCRIPTION
#  Link flags for building against libapreq2
#  REQUIRES
#  libapreq2-devel
#****
APREQ2_LIBS="$(${APREQ2_CONFIG} --link-ld)"

fi  #  check_prog apreq2-config  #

#****C* httpd.cygclass/httpd_mod_compile
#  SYNOPSIS
#  httpd_mod_compile [CONFIGURE_FLAGS]
#  DESCRIPTION
#  Build a DSO which uses an autoconf/libtool buildsystem by calling cygconf
#  and cygmake with some Apache-specific flags.  Arguments, if any, are passed
#  as configure flags.
#  NOTE
#  This is very generic and may not work in all cases.
#****
httpd_mod_compile() {
	if ! defined HTTPD_MOD_NAME
	then
		error "define HTTPD_MOD_NAME before calling httpd_mod_compile"
	fi

	cygconf \
		--with-apxs=${HTTPD_APXS} \
		--with-apr-config=${APR_CONFIG} \
		"${@}"

	cygmake \
		${HTTPD_MOD_NAME}_la_CPPFLAGS="${HTTPD_CFLAGS}" \
		${HTTPD_MOD_NAME}_la_LDFLAGS="-module -avoid-version -no-undefined -shrext .so" \
		${HTTPD_MOD_NAME}_la_LIBADD="${HTTPD_LIBS}"
}

#****C* httpd.cygclass/httpd_apxs_compile
#  SYNOPSIS
#  httpd_apxs_compile [CFLAGS] SOURCES [LIBS]
#  DESCRIPTION
#  Uses HTTPD_APXS to build a DSO from one or more .c source files which ship
#  without their own build system.
#  ARGUMENTS
#  - CFLAGS -- Additional CFLAGS required for compiling this DSO.
#  - SOURCES -- One or more .c sources.
#  - LIBS -- Additional libraries required for linking this DSO.  Must be last.
#****
httpd_apxs_compile() {
	if ! defined HTTPD_MOD_NAME
	then
		error "define HTTPD_MOD_NAME before calling httpd_apxs_compile"
	fi

	${HTTPD_APXS} -c -o ${HTTPD_MOD_NAME}.la -Wc,"${CFLAGS}" "${@:-*.c}" \
		|| error "httpd_apxs_compile failed"
}

#****I* httpd.cygclass/dohttpdconf
#  SYNOPSIS
#  dohttpdconf CONF_FILE [CONF_FILE] ...
#  DESCRIPTION
#  Installs additional Apache configuration files.
#  NOTE
#  All files passed to dohttpdconf will be concenated into one file named
#  HTTPD_MOD_NAME.conf.  Therefore, this must only be called once.
#****
dohttpdconf() {
	local f

	dodir ${HTTPD_SYSCONFDIR}

	for f
	do
		if [ -e ${f} ]
		then
			cat ${f} >> ${D}${HTTPD_SYSCONFDIR}/${HTTPD_MOD_NAME}.conf
		fi
	done
}

#****I* httpd.cygclass/dohttpdmod
#  SYNOPSIS
#  dohttpdmod DSO [DSO] ...
#  DESCRIPTION
#  Installs one or more DSOs into $D/HTTPD_LIBEXECDIR.  DSOs are usually
#  a .la libtool library (whether build with httpd_mod_compile or httpd_apxs_compile),
#  but may also be a .so DLL if built without libtool.
#****
dohttpdmod() {
	local mod modf

	dodir ${HTTPD_LIBEXECDIR}

	for mod
	do
		case ${mod##*.} in
		${mod})	mod=${mod}.la ;;
		esac
		modf=${mod##*/}

		if [ ! -f ${mod} ]
		then
			error "dohttpdmod: ${mod}: File not found"
		fi

		case ${mod} in
		*.la)
			__doinstall 0755 ${mod} ${HTTPD_LIBEXECDIR} \
				|| error "install ${mod} failed"
			[ -f ${D}${HTTPD_LIBEXECDIR}/${modf%.la}.so ] \
				|| error "install ${mod} was incorrectly linked, ${modf%.la}.so not found"
			rm -f ${D}${HTTPD_LIBEXECDIR}/${modf%.*}.{a,dll.a,la}
			;;
		*.so)
			__doinstall 0755 ${mod} ${HTTPD_LIBEXECDIR} \
				|| error "install ${mod} failed"
			;;
		*)	error "dohttpdmod: ${mod##*/}: Unknown file type"
		esac
	done
}

#****I* httpd.cygclass/httpd_loadmodules
#  SYNOPSIS
#  httpd_loadmodules
#  DESCRIPTION
#  Creates a LoadModule configuration snippet in HTTPD_SYSCONFMODULESDIR.
#  This means that users need not do anything more than install the package in
#  order to enable the DSO.  For modules which require further configuration,
#  create a complete file and use dohttpdconf to install it.
#****
httpd_loadmodules() {
	local dso imp mod sym

	dodir ${HTTPD_SYSCONFMODULESDIR}

	for mod in ${D}${HTTPD_LIBEXECDIR}/*.so
	do
		imp=${mod%.so}.dll.a
		dso=${mod##*/}
		dso=${dso%.*}

		if [ -f ${imp} ]
		then
			sym=$(nm ${imp} 2>/dev/null | sed -n -e 's|.* I __nm_${ARCH_i686+_}\(.*_module\)$|\1|p')
		fi

		if ! defined sym
		then
			sym=$(nm -C ${mod} 2>/dev/null | sed -n -e 's|.* D \(.*_module\)$|\1|p')
		fi

		if ! defined sym
		then
			case ${dso} in
			mod_*)	sym=${dso:4}_module ;;
			cyg*|lib*)	sym=${dso:3}_module ;;
			esac
		fi

		if ! ${OBJDUMP} -p ${mod} 2> /dev/null | grep -q "\].* ${sym}$"
		then
			error "Cannot determine module symbol name for ${mod##*/}"
		fi

		cat >> ${D}${HTTPD_SYSCONFMODULESDIR}/${dso}.conf <<-_EOF
			LoadModule ${sym} modules/${mod##*/}
			_EOF

	done
}

readonly -f httpd_mod_compile httpd_apxs_compile dohttpdconf \
            dohttpdmod httpd_loadmodules
