#!/bin/sh
#
# This file is part of OpenMediaVault.
#
# @license   http://www.gnu.org/licenses/gpl.html GPL Version 3
# @author    Volker Theile <volker.theile@openmediavault.org>
# @copyright Copyright (c) 2009-2020 Volker Theile
#
# OpenMediaVault 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
# any later version.
#
# OpenMediaVault 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 OpenMediaVault. If not, see <http://www.gnu.org/licenses/>.

# Documentation/Howto:
# http://wiki.dreamhost.com/index.php/Crontab/
# https://www.systutorials.com/docs/linux/man/5-clamd.conf/
# https://www.systutorials.com/docs/linux/man/5-freshclam.conf/

set -e

. /etc/default/openmediavault
. /usr/share/openmediavault/scripts/helper-functions

OMV_CLAMAV_CLAMD_CONFIG=${OMV_CLAMAV_CLAMD_CONFIG:-"/etc/clamav/clamd.conf"}
OMV_CLAMAV_CLAMD_LOCALSOCKET=${OMV_CLAMAV_CLAMD_LOCALSOCKET:-"/var/run/clamav/clamd.ctl"}
OMV_CLAMAV_CLAMD_LOCALSOCKETGROUP=${OMV_CLAMAV_CLAMD_LOCALSOCKETGROUP:-"clamav"}
OMV_CLAMAV_CLAMD_LOCALSOCKETMODE=${OMV_CLAMAV_CLAMD_LOCALSOCKETMODE:-"666"}
OMV_CLAMAV_CLAMD_USER=${OMV_CLAMAV_CLAMD_USER:-"clamav"}
OMV_CLAMAV_CLAMD_MAXDIRECTORYRECURSION=${OMV_CLAMAV_CLAMD_MAXDIRECTORYRECURSION:-"15"}
OMV_CLAMAV_CLAMD_READTIMEOUT=${OMV_CLAMAV_CLAMD_READTIMEOUT:-"180"}
OMV_CLAMAV_CLAMD_MAXTHREADS=${OMV_CLAMAV_CLAMD_MAXTHREADS:-"12"}
OMV_CLAMAV_CLAMD_MAXCONNECTIONQUEUELENGTH=${OMV_CLAMAV_CLAMD_MAXCONNECTIONQUEUELENGTH:-"15"}
OMV_CLAMAV_CLAMD_SELFCHECK=${OMV_CLAMAV_CLAMD_SELFCHECK:-"3600"}
OMV_CLAMAV_CLAMD_LOGSYSLOG=${OMV_CLAMAV_CLAMD_LOGSYSLOG:-"false"}
OMV_CLAMAV_CLAMD_LOGROTATE=${OMV_CLAMAV_CLAMD_LOGROTATE:-"false"}
OMV_CLAMAV_CLAMD_LOGFACILITY=${OMV_CLAMAV_CLAMD_LOGFACILITY:-"LOG_LOCAL6"}
OMV_CLAMAV_CLAMD_LOGVERBOSE=${OMV_CLAMAV_CLAMD_LOGVERBOSE:-"false"}
OMV_CLAMAV_CLAMD_DATABASEDIRECTORY=${OMV_CLAMAV_CLAMD_DATABASEDIRECTORY:-"/var/lib/clamav"}
OMV_CLAMAV_CLAMD_IDLETIMEOUT=${OMV_CLAMAV_CLAMD_IDLETIMEOUT:-"30"}
OMV_CLAMAV_CLAMD_STREAMMAXLENGTH=${OMV_CLAMAV_CLAMD_STREAMMAXLENGTH:-"25M"}
OMV_CLAMAV_CLAMD_LOGFILE=${OMV_CLAMAV_CLAMD_LOGFILE:-"/var/log/clamav/clamav.log"}
OMV_CLAMAV_CLAMD_LOGROTATE_CONFIG=${OMV_CLAMAV_CLAMD_LOGROTATE_CONFIG:-"/etc/logrotate.d/clamav-daemon"}
OMV_CLAMAV_CLAMD_EXITONOOM=${OMV_CLAMAV_CLAMD_EXITONOOM:-"false"}
OMV_CLAMAV_CLAMD_PHISHINGSCANURLS=${OMV_CLAMAV_CLAMD_PHISHINGSCANURLS:-"false"}
OMV_CLAMAV_CLAMD_PHISHINGALWAYSBLOCKSSLMISMATCH=${OMV_CLAMAV_CLAMD_PHISHINGALWAYSBLOCKSSLMISMATCH:-"false"}
OMV_CLAMAV_CLAMD_PHISHINGALWAYSBLOCKCLOAK=${OMV_CLAMAV_CLAMD_PHISHINGALWAYSBLOCKCLOAK:-"false"}
OMV_CLAMAV_CLAMD_SCANPARTIALMESSAGES=${OMV_CLAMAV_CLAMD_SCANPARTIALMESSAGES:-"false"}
OMV_CLAMAV_CLAMD_HEURISTICSCANPRECEDENCE=${OMV_CLAMAV_CLAMD_HEURISTICSCANPRECEDENCE:-"false"}
OMV_CLAMAV_CLAMD_STRUCTUREDDATADETECTION=${OMV_CLAMAV_CLAMD_STRUCTUREDDATADETECTION:-"false"}
OMV_CLAMAV_CLAMD_EXTENDEDDETECTIONINFO=${OMV_CLAMAV_CLAMD_EXTENDEDDETECTIONINFO:-"true"}
OMV_CLAMAV_CLAMD_SCANMAIL=${OMV_CLAMAV_CLAMD_SCANMAIL:-"false"}
OMV_CLAMAV_CLAMD_DEBUG=${OMV_CLAMAV_CLAMD_DEBUG:-"false"}
OMV_CLAMAV_CLAMD_ARCHIVEBLOCKENCRYPTED=${OMV_CLAMAV_CLAMD_ARCHIVEBLOCKENCRYPTED:-"false"}
OMV_CLAMAV_CLAMD_COMMANDREADTIMEOUT=${OMV_CLAMAV_CLAMD_COMMANDREADTIMEOUT:-"5"}
OMV_CLAMAV_CLAMD_SENDBUFTIMEOUT=${OMV_CLAMAV_CLAMD_SENDBUFTIMEOUT:-"200"}
OMV_CLAMAV_CLAMD_MAXQUEUE=${OMV_CLAMAV_CLAMD_MAXQUEUE:-"100"}
OMV_CLAMAV_CLAMD_OFFICIALDATABASEONLY=${OMV_CLAMAV_CLAMD_OFFICIALDATABASEONLY:-"false"}
OMV_CLAMAV_CLAMD_CROSSFILESYSTEMS=${OMV_CLAMAV_CLAMD_CROSSFILESYSTEMS:-"true"}
OMV_CLAMAV_CLAMD_LEAVETEMPORARYFILES=${OMV_CLAMAV_CLAMD_LEAVETEMPORARYFILES:-"false"}
OMV_CLAMAV_CLAMD_PHISHINGSIGNATURES=${OMV_CLAMAV_CLAMD_PHISHINGSIGNATURES:-"true"}
OMV_CLAMAV_CLAMD_OLE2BLOCKMACROS=${OMV_CLAMAV_CLAMD_OLE2BLOCKMACROS:-"false"}
OMV_CLAMAV_CLAMD_VIRUSEVENT=${OMV_CLAMAV_CLAMD_VIRUSEVENT:-"/bin/run-parts --lsbsysinit -- /etc/clamav/virusevent.d/"}
OMV_CLAMAV_CLAMD_MAXEMBEDDEDPE=${OMV_CLAMAV_CLAMD_MAXEMBEDDEDPE:-"10M"}
OMV_CLAMAV_CLAMD_MAXHTMLNORMALIZE=${OMV_CLAMAV_CLAMD_MAXHTMLNORMALIZE:-"10M"}
OMV_CLAMAV_CLAMD_MAXHTMLNOTAGS=${OMV_CLAMAV_CLAMD_MAXHTMLNOTAGS:-"2M"}
OMV_CLAMAV_CLAMD_MAXSCRIPTNORMALIZE=${OMV_CLAMAV_CLAMD_MAXSCRIPTNORMALIZE:-"5M"}
OMV_CLAMAV_CLAMD_MAXZIPTYPERCG=${OMV_CLAMAV_CLAMD_MAXZIPTYPERCG:-"1M"}
OMV_CLAMAV_CLAMD_SCANSWF=${OMV_CLAMAV_CLAMD_SCANSWF:-"true"}
OMV_CLAMAV_CLAMD_PARTITIONINTERSECTION=${OMV_CLAMAV_CLAMD_PARTITIONINTERSECTION:-"false"}
OMV_CLAMAV_CLAMD_ALLOWALLMATCHSCAN=${OMV_CLAMAV_CLAMD_ALLOWALLMATCHSCAN:-"true"}
OMV_CLAMAV_CLAMD_FORCETODISK=${OMV_CLAMAV_CLAMD_FORCETODISK:-"false"}
OMV_CLAMAV_CLAMD_DISABLECERTCHECK=${OMV_CLAMAV_CLAMD_DISABLECERTCHECK:-"false"}
OMV_CLAMAV_CLAMD_DISABLECACHE=${OMV_CLAMAV_CLAMD_DISABLECACHE:-"false"}
OMV_CLAMAV_CLAMD_MAXSCANSIZE=${OMV_CLAMAV_CLAMD_MAXSCANSIZE:-"100M"}
OMV_CLAMAV_CLAMD_MAXFILESIZE=${OMV_CLAMAV_CLAMD_MAXFILESIZE:-"25M"}
OMV_CLAMAV_CLAMD_MAXRECURSION=${OMV_CLAMAV_CLAMD_MAXRECURSION:-"16"}
OMV_CLAMAV_CLAMD_MAXFILES=${OMV_CLAMAV_CLAMD_MAXFILES:-"10000"}
OMV_CLAMAV_CLAMD_MAXPARTITIONS=${OMV_CLAMAV_CLAMD_MAXPARTITIONS:-"50"}
OMV_CLAMAV_CLAMD_MAXICONSPE=${OMV_CLAMAV_CLAMD_MAXICONSPE:-"100"}
OMV_CLAMAV_CLAMD_PCREMATCHLIMIT=${OMV_CLAMAV_CLAMD_PCREMATCHLIMIT:-"10000"}
OMV_CLAMAV_CLAMD_PCRERECMATCHLIMIT=${OMV_CLAMAV_CLAMD_PCRERECMATCHLIMIT:-"5000"}
OMV_CLAMAV_CLAMD_PCREMAXFILESIZE=${OMV_CLAMAV_CLAMD_PCREMAXFILESIZE:-"25M"}
OMV_CLAMAV_CLAMD_SCANXMLDOCS=${OMV_CLAMAV_CLAMD_SCANXMLDOCS:-"true"}
OMV_CLAMAV_CLAMD_SCANHWP3=${OMV_CLAMAV_CLAMD_SCANHWP3:-"true"}
OMV_CLAMAV_CLAMD_MAXRECHWP3=${OMV_CLAMAV_CLAMD_MAXRECHWP3:-"16"}
OMV_CLAMAV_CLAMD_LOGTIME=${OMV_CLAMAV_CLAMD_LOGTIME:-"true"}
OMV_CLAMAV_CLAMD_LOGFILEUNLOCK=${OMV_CLAMAV_CLAMD_LOGFILEUNLOCK:-"false"}
OMV_CLAMAV_CLAMD_LOGFILEMAXSIZE=${OMV_CLAMAV_CLAMD_LOGFILEMAXSIZE:-"0"}
OMV_CLAMAV_CLAMD_BYTECODE=${OMV_CLAMAV_CLAMD_BYTECODE:-"true"}
OMV_CLAMAV_CLAMD_BYTECODESECURITY=${OMV_CLAMAV_CLAMD_BYTECODESECURITY:-"TrustSigned"}
OMV_CLAMAV_CLAMD_BYTECODETIMEOUT=${OMV_CLAMAV_CLAMD_BYTECODETIMEOUT:-"60000"}
OMV_CLAMAV_CLAMD_ONACCESSMAXFILESIZE=${OMV_CLAMAV_CLAMD_ONACCESSMAXFILESIZE:-"100M"}
OMV_CLAMAV_CLAMD_ONACCESSMAXTHREADS=${OMV_CLAMAV_CLAMD_ONACCESSMAXTHREADS:-"5"}
OMV_CLAMAV_CLAMD_ONACCESSDISABLEDDD=${OMV_CLAMAV_CLAMD_ONACCESSDISABLEDDD:-"false"}
OMV_CLAMAV_CLAMD_ONACCESSPREVENTION=${OMV_CLAMAV_CLAMD_ONACCESSPREVENTION:-"true"}
OMV_CLAMAV_CLAMD_ONACCESSEXTRASCANNING=${OMV_CLAMAV_CLAMD_ONACCESSEXTRASCANNING:-"true"}
OMV_CLAMAV_CLAMD_ONACCESSRETRYATTEMPTS=${OMV_CLAMAV_CLAMD_ONACCESSRETRYATTEMPTS:-"3"}
OMV_CLAMAV_FRESHCLAM_CONFIG=${OMV_CLAMAV_FRESHCLAM_CONFIG:-"/etc/clamav/freshclam.conf"}
OMV_CLAMAV_FRESHCLAM_COMPRESSLOCALDATABASE=${OMV_CLAMAV_FRESHCLAM_COMPRESSLOCALDATABASE:-"no"}
OMV_CLAMAV_FRESHCLAM_DATABASEOWNER=${OMV_CLAMAV_FRESHCLAM_DATABASEOWNER:-"clamav"}
OMV_CLAMAV_FRESHCLAM_DATABASEMIRROR=${OMV_CLAMAV_FRESHCLAM_DATABASEMIRROR:-"database.clamav.net"}
OMV_CLAMAV_FRESHCLAM_UPDATELOGFILE=${OMV_CLAMAV_FRESHCLAM_UPDATELOGFILE:-"/var/log/clamav/freshclam.log"}
OMV_CLAMAV_FRESHCLAM_LOGSYSLOG=${OMV_CLAMAV_FRESHCLAM_LOGSYSLOG:-"false"}
OMV_CLAMAV_FRESHCLAM_LOGVERBOSE=${OMV_CLAMAV_FRESHCLAM_LOGVERBOSE:-"false"}
OMV_CLAMAV_FRESHCLAM_LOGFACILITY=${OMV_CLAMAV_FRESHCLAM_LOGFACILITY:-"LOG_LOCAL6"}
OMV_CLAMAV_FRESHCLAM_LOGFILEMAXSIZE=${OMV_CLAMAV_FRESHCLAM_LOGFILEMAXSIZE:-"0"}
OMV_CLAMAV_FRESHCLAM_LOGROTATE=${OMV_CLAMAV_FRESHCLAM_LOGROTATE:-"false"}
OMV_CLAMAV_FRESHCLAM_DATABASEDIRECTORY=${OMV_CLAMAV_FRESHCLAM_DATABASEDIRECTORY:-"/var/lib/clamav"}
OMV_CLAMAV_FRESHCLAM_DNSDATABASEINFO=${OMV_CLAMAV_FRESHCLAM_DNSDATABASEINFO:-"current.cvd.clamav.net"}
OMV_CLAMAV_FRESHCLAM_NOTIFYCLAMD=${OMV_CLAMAV_FRESHCLAM_NOTIFYCLAMD:-"/etc/clamav/clamd.conf"}
OMV_CLAMAV_FRESHCLAM_LOGROTATE_CONFIG=${OMV_CLAMAV_FRESHCLAM_LOGROTATE_CONFIG:-"/etc/logrotate.d/clamav-freshclam"}
OMV_CLAMAV_FRESHCLAM_CONNECTTIMEOUT=${OMV_CLAMAV_FRESHCLAM_CONNECTTIMEOUT:-"30"}
OMV_CLAMAV_FRESHCLAM_RECEIVETIMEOUT=${OMV_CLAMAV_FRESHCLAM_RECEIVETIMEOUT:-"300"}
OMV_CLAMAV_CLAMDSCAN_CRONSCRIPT=${OMV_CLAMAV_CLAMDSCAN_CRONSCRIPT:-"/etc/cron.d/openmediavault-clamdscan"}
OMV_CLAMAV_CLAMDSCAN_CRONSCRIPT_MASK=${OMV_CLAMAV_CLAMDSCAN_CRONSCRIPT_MASK:-"755"}
OMV_CLAMAV_CLAMDSCAN_CRONSCRIPT_TEMPLATE=${OMV_CLAMAV_CLAMDSCAN_CRONSCRIPT_TEMPLATE:-"clamdscan-"}
OMV_CLAMAV_CLAMDSCAN_CMDARGS=${OMV_CLAMAV_CLAMDSCAN_CMDARGS:-"--stdout"}

# Create '/etc/clamav/clamd.conf' configuration file.
xmlstarlet sel -t -m "//services/clamav/clamd" \
  -o "LocalSocket ${OMV_CLAMAV_CLAMD_LOCALSOCKET}" -n \
  -o "FixStaleSocket true" -n \
  -o "LocalSocketGroup ${OMV_CLAMAV_CLAMD_LOCALSOCKETGROUP}" -n \
  -o "LocalSocketMode ${OMV_CLAMAV_CLAMD_LOCALSOCKETMODE}" -n \
  -o "AlertEncrypted ${OMV_CLAMAV_CLAMD_ARCHIVEBLOCKENCRYPTED}" -n \
  -o "AlertEncryptedArchive ${OMV_CLAMAV_CLAMD_ARCHIVEBLOCKENCRYPTED}" -n \
  -o "AlertEncryptedDoc ${OMV_CLAMAV_CLAMD_ARCHIVEBLOCKENCRYPTED}" -n \
  -o "MaxDirectoryRecursion ${OMV_CLAMAV_CLAMD_MAXDIRECTORYRECURSION}" -n \
  -v "concat('FollowDirectorySymlinks ',followdirectorysymlinks)" -n \
  -v "concat('FollowFileSymlinks ',followfilesymlinks)" -n \
  -o "ReadTimeout ${OMV_CLAMAV_CLAMD_READTIMEOUT}" -n \
  -o "MaxThreads ${OMV_CLAMAV_CLAMD_MAXTHREADS}" -n \
  -o "MaxConnectionQueueLength ${OMV_CLAMAV_CLAMD_MAXCONNECTIONQUEUELENGTH}" -n \
  -o "LogSyslog ${OMV_CLAMAV_CLAMD_LOGSYSLOG}" -n \
  -o "LogRotate ${OMV_CLAMAV_CLAMD_LOGROTATE}" -n \
  -o "LogFacility ${OMV_CLAMAV_CLAMD_LOGFACILITY}" -n \
  -v "concat('LogClean ',logclean)" -n \
  -o "LogVerbose ${OMV_CLAMAV_CLAMD_LOGVERBOSE}" -n \
  -o "DatabaseDirectory ${OMV_CLAMAV_CLAMD_DATABASEDIRECTORY}" -n \
  -o "SelfCheck ${OMV_CLAMAV_CLAMD_SELFCHECK}" -n \
  -o "Foreground false" -n \
  -o "Debug ${OMV_CLAMAV_CLAMD_DEBUG}" -n \
  -v "concat('ScanPE ',scanpe)" -n \
  -o "MaxEmbeddedPE ${OMV_CLAMAV_CLAMD_MAXEMBEDDEDPE}" -n \
  -v "concat('ScanOLE2 ',scanole2)" -n \
  -v "concat('ScanPDF ',scanpdf)" -n \
  -v "concat('ScanHTML ',scanhtml)" -n \
  -o "MaxHTMLNormalize ${OMV_CLAMAV_CLAMD_MAXHTMLNORMALIZE}" -n \
  -o "MaxHTMLNoTags ${OMV_CLAMAV_CLAMD_MAXHTMLNOTAGS}" -n \
  -o "MaxScriptNormalize ${OMV_CLAMAV_CLAMD_MAXSCRIPTNORMALIZE}" -n \
  -o "MaxZipTypeRcg ${OMV_CLAMAV_CLAMD_MAXZIPTYPERCG}" -n \
  -o "ScanSWF ${OMV_CLAMAV_CLAMD_SCANSWF}" -n \
  -v "concat('ScanELF ',scanelf)" -n \
  -v "concat('ScanArchive ',scanarchive)" -n \
  -o "ScanMail ${OMV_CLAMAV_CLAMD_SCANMAIL}" -n \
  -v "concat('AlertBrokenExecutables ',detectbrokenexecutables)" -n \
  -o "ExitOnOOM ${OMV_CLAMAV_CLAMD_EXITONOOM}" -n \
  -o "LeaveTemporaryFiles ${OMV_CLAMAV_CLAMD_LEAVETEMPORARYFILES}" -n \
  -v "concat('HeuristicAlerts ',algorithmicdetection)" -n \
  -o "IdleTimeout ${OMV_CLAMAV_CLAMD_IDLETIMEOUT}" -n \
  -o "PhishingSignatures ${OMV_CLAMAV_CLAMD_PHISHINGSIGNATURES}" -n \
  -o "PhishingScanURLs ${OMV_CLAMAV_CLAMD_PHISHINGSCANURLS}" -n \
  -o "AlertPhishingSSLMismatch ${OMV_CLAMAV_CLAMD_PHISHINGALWAYSBLOCKSSLMISMATCH}" -n \
  -o "AlertPhishingCloak ${OMV_CLAMAV_CLAMD_PHISHINGALWAYSBLOCKCLOAK}" -n \
  -o "AlertPartitionIntersection ${OMV_CLAMAV_CLAMD_PARTITIONINTERSECTION}" -n \
  -v "concat('DetectPUA ',detectpua)" -n \
  -o "ScanPartialMessages ${OMV_CLAMAV_CLAMD_SCANPARTIALMESSAGES}" -n \
  -o "HeuristicScanPrecedence ${OMV_CLAMAV_CLAMD_HEURISTICSCANPRECEDENCE}" -n \
  -o "StructuredDataDetection ${OMV_CLAMAV_CLAMD_STRUCTUREDDATADETECTION}" -n \
  -o "CommandReadTimeout ${OMV_CLAMAV_CLAMD_COMMANDREADTIMEOUT}" -n \
  -o "SendBufTimeout ${OMV_CLAMAV_CLAMD_SENDBUFTIMEOUT}" -n \
  -o "MaxQueue ${OMV_CLAMAV_CLAMD_MAXQUEUE}" -n \
  -o "ExtendedDetectionInfo ${OMV_CLAMAV_CLAMD_EXTENDEDDETECTIONINFO}" -n \
  -o "AlertOLE2Macros ${OMV_CLAMAV_CLAMD_OLE2BLOCKMACROS}" -n \
  -o "AllowAllMatchScan ${OMV_CLAMAV_CLAMD_ALLOWALLMATCHSCAN}" -n \
  -o "ForceToDisk ${OMV_CLAMAV_CLAMD_FORCETODISK}" -n \
  -o "DisableCertCheck ${OMV_CLAMAV_CLAMD_DISABLECERTCHECK}" -n \
  -o "DisableCache ${OMV_CLAMAV_CLAMD_DISABLECACHE}" -n \
  -o "MaxScanSize ${OMV_CLAMAV_CLAMD_MAXSCANSIZE}" -n \
  -o "MaxFileSize ${OMV_CLAMAV_CLAMD_MAXFILESIZE}" -n \
  -o "MaxRecursion ${OMV_CLAMAV_CLAMD_MAXRECURSION}" -n \
  -o "MaxFiles ${OMV_CLAMAV_CLAMD_MAXFILES}" -n \
  -o "MaxPartitions ${OMV_CLAMAV_CLAMD_MAXPARTITIONS}" -n \
  -o "MaxIconsPE ${OMV_CLAMAV_CLAMD_MAXICONSPE}" -n \
  -o "PCREMatchLimit ${OMV_CLAMAV_CLAMD_PCREMATCHLIMIT}" -n \
  -o "PCRERecMatchLimit ${OMV_CLAMAV_CLAMD_PCRERECMATCHLIMIT}" -n \
  -o "PCREMaxFileSize ${OMV_CLAMAV_CLAMD_PCREMAXFILESIZE}" -n \
  -o "ScanXMLDOCS ${OMV_CLAMAV_CLAMD_SCANXMLDOCS}" -n \
  -o "ScanHWP3 ${OMV_CLAMAV_CLAMD_SCANHWP3}" -n \
  -o "MaxRecHWP3 ${OMV_CLAMAV_CLAMD_MAXRECHWP3}" -n \
  -o "StreamMaxLength ${OMV_CLAMAV_CLAMD_STREAMMAXLENGTH}" -n \
  -o "LogFile ${OMV_CLAMAV_CLAMD_LOGFILE}" -n \
  -o "LogTime ${OMV_CLAMAV_CLAMD_LOGTIME}" -n \
  -o "LogFileUnlock ${OMV_CLAMAV_CLAMD_LOGFILEUNLOCK}" -n \
  -o "LogFileMaxSize ${OMV_CLAMAV_CLAMD_LOGFILEMAXSIZE}" -n \
  -o "Bytecode ${OMV_CLAMAV_CLAMD_BYTECODE}" -n \
  -o "BytecodeSecurity ${OMV_CLAMAV_CLAMD_BYTECODESECURITY}" -n \
  -o "BytecodeTimeout ${OMV_CLAMAV_CLAMD_BYTECODETIMEOUT}" -n \
  -o "OfficialDatabaseOnly ${OMV_CLAMAV_CLAMD_OFFICIALDATABASEONLY}" -n \
  -o "CrossFilesystems ${OMV_CLAMAV_CLAMD_CROSSFILESYSTEMS}" -n \
  -o "VirusEvent ${OMV_CLAMAV_CLAMD_VIRUSEVENT}" -n \
  -o "User ${OMV_CLAMAV_CLAMD_USER}" -n \
  -o "OnAccessMaxFileSize ${OMV_CLAMAV_CLAMD_ONACCESSMAXFILESIZE}" -n \
  -o "OnAccessMaxThreads ${OMV_CLAMAV_CLAMD_ONACCESSMAXTHREADS}" -n \
  -o "OnAccessDisableDDD ${OMV_CLAMAV_CLAMD_ONACCESSDISABLEDDD}" -n \
  -o "OnAccessPrevention ${OMV_CLAMAV_CLAMD_ONACCESSPREVENTION}" -n \
  -o "OnAccessExtraScanning ${OMV_CLAMAV_CLAMD_ONACCESSEXTRASCANNING}" -n \
  -o "OnAccessExcludeUname ${OMV_CLAMAV_CLAMD_USER}" -n \
  -o "OnAccessRetryAttempts ${OMV_CLAMAV_CLAMD_ONACCESSRETRYATTEMPTS}" -n \
  -i "count(//services/clamav/onaccesspaths/onaccesspath[enable='1']) > 0" \
    -m "//services/clamav/onaccesspaths/onaccesspath[enable='1']" \
      -o "OnAccessIncludePath " ${OMV_XMLSTARLET_GET_SHAREDFOLDER_PATH} -n \
    -b \
  -b \
  -i "string-length(extraoptions) > 0" -v extraoptions -n -b \
  ${OMV_CONFIG_FILE} | xmlstarlet unesc > ${OMV_CLAMAV_CLAMD_CONFIG}

# Create '/etc/clamav/freshclam.conf' configuration file.
xmlstarlet sel -t \
  -m "//services/clamav/freshclam" \
    -o "DatabaseOwner ${OMV_CLAMAV_FRESHCLAM_DATABASEOWNER}" -n \
    -o "UpdateLogFile ${OMV_CLAMAV_FRESHCLAM_UPDATELOGFILE}" -n \
    -o "LogVerbose ${OMV_CLAMAV_FRESHCLAM_LOGVERBOSE}" -n \
    -o "LogSyslog ${OMV_CLAMAV_FRESHCLAM_LOGSYSLOG}" -n \
    -o "LogFacility ${OMV_CLAMAV_FRESHCLAM_LOGFACILITY}" -n \
    -o "LogFileMaxSize ${OMV_CLAMAV_FRESHCLAM_LOGFILEMAXSIZE}" -n \
    -o "LogRotate ${OMV_CLAMAV_FRESHCLAM_LOGROTATE}" -n \
    -o "LogTime true" -n \
    -o "Foreground false" -n \
    -o "Debug false" -n \
    -o "MaxAttempts 5" -n \
    -o "DatabaseDirectory ${OMV_CLAMAV_FRESHCLAM_DATABASEDIRECTORY}" -n \
    -o "DNSDatabaseInfo ${OMV_CLAMAV_FRESHCLAM_DNSDATABASEINFO}" -n \
    -o "ConnectTimeout ${OMV_CLAMAV_FRESHCLAM_CONNECTTIMEOUT}" -n \
    -o "ReceiveTimeout ${OMV_CLAMAV_FRESHCLAM_RECEIVETIMEOUT}" -n \
    -o "TestDatabases yes" -n \
    -o "ScriptedUpdates yes" -n \
    -o "CompressLocalDatabase ${OMV_CLAMAV_FRESHCLAM_COMPRESSLOCALDATABASE}" -n \
    -o "SafeBrowsing false" -n \
    -o "Bytecode true" -n \
    -o "NotifyClamd ${OMV_CLAMAV_FRESHCLAM_NOTIFYCLAMD}" -n \
    -v "concat('Checks ',checks)" -n \
    -o "DatabaseMirror ${OMV_CLAMAV_FRESHCLAM_DATABASEMIRROR}" -n \
  -b \
  -m "//system/network/proxy/http" \
    -i "enable = '1' and string-length(host) > 0" \
      -v "concat('HTTPProxyServer ',host)" -n \
	  -v "concat('HTTPProxyPort ',port)" -n \
      -i "string-length(username) > 0" \
	    -v "concat('HTTPProxyUsername ',username)" -n \
		-v "concat('HTTPProxyPassword ',password)" -n \
	  -b \
  -b \
  ${OMV_CONFIG_FILE} | xmlstarlet unesc > ${OMV_CLAMAV_FRESHCLAM_CONFIG}

# Get the quarantine shared folder.
sfref=$(omv_config_get "//services/clamav/quarantine/sharedfolderref")
sfpath=$(omv_get_sharedfolder_path "${sfref}")

# Create the cron jobs.
rm -f ${OMV_CRONSCRIPTS_DIR}/${OMV_CLAMAV_CLAMDSCAN_CRONSCRIPT_TEMPLATE}*
xmlstarlet sel -t \
  -m "//services/clamav/jobs/job[enable='1']" \
    -v "uuid" -n \
  -b \
  ${OMV_CONFIG_FILE} | xmlstarlet unesc |
  while read uuid; do
	  filename="${OMV_CRONSCRIPTS_DIR}/${OMV_CLAMAV_CLAMDSCAN_CRONSCRIPT_TEMPLATE}${uuid}"
	  runfile="/var/run/${OMV_CLAMAV_CLAMDSCAN_CRONSCRIPT_TEMPLATE}${uuid}"

	  xmlstarlet sel -t -m "//services/clamav/jobs/job[uuid='${uuid}']" \
		-o "#!/bin/sh" -n \
		-o "# This configuration file is auto-generated." -n \
		-o "# WARNING: Do not edit this file, your changes will be lost." -n \
		-o ". /usr/share/openmediavault/scripts/helper-functions" -n \
		-o "cleanup() {" -n \
		-o "  omv_kill_children \$\$" -n \
		-o "  rm -f ${runfile}" -n \
		-o "  exit" -n \
		-o "}" -n \
		-o "[ -e ${runfile} ] && exit 1" -n \
		-o "trap cleanup 0 1 2 5 15" -n \
		-o "touch ${runfile}" -n \
		-o "omv_log \"Please wait, scanning shared folder <" ${OMV_XMLSTARLET_GET_SHAREDFOLDER_NAME} -o "> ...\n\"" -n \
		-o "clamdscan ${OMV_CLAMAV_CLAMDSCAN_CMDARGS}" \
		-i "virusaction[. = 'delete']" -o " --remove" -b \
		-i "virusaction[. = 'quarantine']" -o " --move=\"${sfpath}\"" -b \
		-i "multiscan[. = '1']" -o " --multiscan" -b \
		-i "verbose[. = '1']" -o " --verbose" -b \
		-o " \"" ${OMV_XMLSTARLET_GET_SHAREDFOLDER_PATH} -o "\" & wait \$!" \
		${OMV_CONFIG_FILE} | xmlstarlet unesc > ${filename}
	  chmod ${OMV_CLAMAV_CLAMDSCAN_CRONSCRIPT_MASK} ${filename}
  done
xmlstarlet sel -t \
  -o "SHELL=/bin/sh" -n \
  -o "PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin" -n \
  -o "# m h dom mon dow user    command" -n \
  -m "//services/clamav[enable='1']" \
	  -m "//services/clamav/jobs/job[enable='1']" \
		  -i "everynminute[. = '1']" -v "concat('*/',minute,' ')" -b \
		  -i "everynminute[. = '0']" -v "concat(minute,' ')" -b \
		  -i "everynhour[. = '1']" -v "concat('*/',hour,' ')" -b \
		  -i "everynhour[. = '0']" -v "concat(hour,' ')" -b \
		  -i "everyndayofmonth[. = '1']" -v "concat('*/',dayofmonth,' ')" -b \
		  -i "everyndayofmonth[. = '0']" -v "concat(dayofmonth,' ')" -b \
		  -v "concat(month,' ',dayofweek,' root ${OMV_CRONSCRIPTS_DIR}/${OMV_CLAMAV_CLAMDSCAN_CRONSCRIPT_TEMPLATE}',uuid)" \
		  -i "sendemail[. = '0']" \
			  -o " >/dev/null 2>&1" \
		  -b \
		  -i "sendemail[. = '1']" \
			-i "string-length(comment) > 0" \
			  -v "concat(' | mail -E -s \"ClamAV - ',translate(comment,'\

',' '),'\" -a \"From: Cron Daemon <root>\" root >/dev/null 2>&1')" \
			-b \
		  -b \
		  -n \
	-b \
  -b \
  ${OMV_CONFIG_FILE} | xmlstarlet unesc > ${OMV_CLAMAV_CLAMDSCAN_CRONSCRIPT}
chmod 644 ${OMV_CLAMAV_CLAMDSCAN_CRONSCRIPT}

# Create the logrotate configuration files.
rm -f ${OMV_CLAMAV_CLAMD_LOGROTATE_CONFIG}
rm -f ${OMV_CLAMAV_FRESHCLAM_LOGROTATE_CONFIG}
if [ "$(omv_config_get "//services/clamav/enable")" = "1" ]; then
    # Create the clamav-daemon logrotate configuration file.
    cat <<EOF > ${OMV_CLAMAV_CLAMD_LOGROTATE_CONFIG}
${OMV_CLAMAV_CLAMD_LOGFILE} {
	rotate 12
	weekly
	compress
	delaycompress
	create 640 ${OMV_CLAMAV_CLAMD_USER} adm
	postrotate
	if [ -d /run/systemd/system ]; then
		systemctl -q is-active clamav-daemon && systemctl kill --signal=SIGHUP clamav-daemon
	else
		/etc/init.d/clamav-daemon reload-log > /dev/null
	fi
	endscript
}
EOF
    chown ${OMV_CLAMAV_CLAMD_USER}:root "${OMV_CLAMAV_CLAMD_LOGROTATE_CONFIG}"
    chmod 0644 "${OMV_CLAMAV_CLAMD_LOGROTATE_CONFIG}"

    # Create the clamav-freshclam logrotate configuration file.
    if [ "$(omv_config_get "//services/clamav/freshclam/enable")" = "1" ]; then
        cat <<EOF > ${OMV_CLAMAV_FRESHCLAM_LOGROTATE_CONFIG}
${OMV_CLAMAV_FRESHCLAM_UPDATELOGFILE} {
	rotate 12
	weekly
	compress
	delaycompress
	missingok
	create 640 ${OMV_CLAMAV_FRESHCLAM_DATABASEOWNER} adm
	postrotate
	if [ -d /run/systemd/system ]; then
		systemctl -q is-active clamav-freshclam && systemctl kill --signal=SIGHUP clamav-freshclam
	else
		/etc/init.d/clamav-freshclam reload-log > /dev/null
	fi
	endscript
}
EOF
        chown ${OMV_CLAMAV_FRESHCLAM_DATABASEOWNER}:root "${OMV_CLAMAV_FRESHCLAM_LOGROTATE_CONFIG}"
        chmod 0644 "${OMV_CLAMAV_FRESHCLAM_LOGROTATE_CONFIG}"
    fi
fi

# If Apparmor is installed and enabled, we need to make sure that the
# shared folders are accessible by clamd.
sed --in-place --regexp-extended "s|#(include <local/usr\.sbin\.clamd>)|\1|" "/etc/apparmor.d/usr.sbin.clamd"
if ! grep --fixed-strings "/srv/** krw," "/etc/apparmor.d/local/usr.sbin.clamd" >/dev/null; then
  echo "/srv/** krw," >> "/etc/apparmor.d/local/usr.sbin.clamd"
fi
