# main.tcl
# LEG06042005
#
# based on aolserver4.tcl shipped with Debians aolserver4.deb
#    Copyright (C) 2003 Francesco P. Lovergine <frankie@debian.org> GPL
# and Vinod Kurup: http://panoptic.com/wiki/aolserver/98
#

#### this file is not user servicable ##############################
ns_log notice "nsd: reading main.tcl"

# Different directories:
# confdir:      configuration file hierarchy
# vardir:       variable data, namely tdav locks and properties
# homedir:      Aolserver home, used internally
# logdir:       logfiles
# piddir:       directory for .pid files

set package 	aolserver4
set confname    domains.cfg

set confdir     /etc/${package}
set homedir 	/usr/lib/${package}
set vardir      /var/lib
set logdir      /var/log/${package}
set piddir      /var/run/${package}
# TODO: platform compatibility
set serverroot	/var/www

# We handle certs and permission files centrally
set permdir perms
set certdir certs
set ca_dir  certs

# php wrapper hack, unset to disable
set php_wrapper "/usr/local/sbin/aolserver-php5-cgi-wrapper"

# Utility procedures for location of configfiles, defaults and logs
# Locate a relative filename in $confdir, else at its original place
proc conffile {args} {
    global confdir
    return [eval file join ${confdir} $args]
}
# Locate a relative filename in $homedir, else at its original place
# homedir is /usr/lib... therefore: libraryfile
proc libfile {args} {
    global homedir
    return [eval file join ${homedir} $args]
}
# logfiles
proc logfile {args} {
    global logdir
    return [eval file join ${logdir} $args]
}

# Modulelist:
# We exclude by default:  nsxml nsimap nscp nsext
# Also:
# the database drivers are loaded within nsdb: nspostgres
# nssock is loaded by the main server or if an individual IP is
# specified in a server.
# nsldap is loaded automagically if a pool is specified in the
# configuration file

set modulelist  {
    nslog nssha1 nscache nsdb nsopenssl nscgi nsperm nsldap
}
set modext ".so"

# Prepare parsing of the configuration file
proc server {name description parameters} {

    global array conf
    global array servers

    set servers($name) $description

    # first server is defaultserver, unless overridden
    if ![info exists conf(defaultserver)] {
	set conf(defaultserver) $name
    }

    foreach {token value} $parameters {
	switch $token {
	    defaultserver {
		if $value { set conf(defaultserver) $name }
	    }

	    fqdn { append conf($name,domains) " " $value }
	    bind { 
		set bind [split $value :]
		set conf($name,address) [lindex $bind 0]
		set conf($name,httpport)    [lindex $bind 1]
	    }
	    bindssl {
		set bind [split $value :]
		set conf($name,httpsaddress) [lindex $bind 0]
		set conf($name,httpsport)    [lindex $bind 1]
	    }
	    http {
		set conf($name,address) "0.0.0.0"
		set conf($name,httpport)    "80"
	    }
	    https {
		set conf($name,httpsaddress) "0.0.0.0"
		set conf($name,httpsport)    "443"
	    }
            dav_share {
		lappend conf($name,shares) $value
	    }
	    dav_uri -
	    dav_description -
	    dav_options -
	    dav_users -
	    dav_groups {
		# store value in conf(server,share,token)
		set conf($name,[lindex $conf($name,shares) end],$token) $value
	    }
	    
	    default { set conf($name,$token) $value }
	}
    }
    if ![info exists conf($name,hostname)] {
	set conf($name,hostname) [lindex $conf($name,domains) 0]
    }
}

# nsldap parameters
proc ldap {pool parameters} {

    global array ldap
    global ldappools
    
    # remember pool-name
    append ldappools $pool " "

    foreach {token value} $parameters {
	set ldap(${pool},$token) $value
    }
}


source [conffile $confname]

#
# set global defaults
#

if ![info exists debug] { set debug false }
if ![info exists directoryfile] {
    set directoryfile "index.tcl,index.adp,index.html,index.htm" 
}

if ![info exists defaultserver] {
    set defaultserver $conf(defaultserver)
}

# stacksize per thread in Kilobytes
if ![info exists stack] {
    set stack 128
}


# Debug/Compile the configuration
if {[info exists confdebug] && $confdebug}  {
    proc ns_section_new {section} {
	puts "\nns_section $section"
	ns_section $section
    }
    proc ns_param_new {param value} {
	puts "ns_param $param \"$value\""
	ns_param $param $value
    }
    proc ns_log_new {severity text} {
	puts "\n\# $severity: $text"
	ns_log $severity $text
    }
    set ns_section "ns_section_new"
    set ns_param   "ns_param_new"
    set ns_log     "ns_log_new"
} else {
    set ns_section "ns_section"
    set ns_param   "ns_param"
    set ns_log     "ns_log"
}



$ns_log notice "nsd: Virtual domain configurations"

$ns_section ns/module/nssock/servers
foreach {server description} [array get servers] {
    foreach fqdn $conf($server,domains) {
	$ns_param ${server} $fqdn
    }
}

# List of server entries with individual configuration
$ns_section "ns/servers"
foreach {server description} [array get servers] {
    $ns_param $server            $description
}

# For each server entry, source the respective configuration file
#
foreach {server description} [array get servers] {

    # Set per server default parameters

    if ![info exists conf(${server},skip)] {
	set conf(${server},skip)  false
    }
    if ![info exists conf(${server},root)] {
	set conf(${server},root)  $serverroot
    }
    # pageroot can be expressed relative to the serverroot
    if [info exists conf(${server},pageroot)] {
	set conf(${server},pageroot)  [file join $conf(${server},root) $conf($server,pageroot)]
    } else {
	set conf(${server},pageroot)  [file join $conf(${server},root) ${server}]
    }

    # interface binding
    # TODO: if token http but value not yes, do not set up a http socket.
    if ![info exists conf(${server},address)] {
	set conf(${server},address)  0.0.0.0
    }
    if ![info exists conf(${server},httpport)] {
	set conf(${server},httpport)  80
    }

    # tcl library:
    if ![info exists conf(${server},tcllibrary)] {
	set conf(${server},tcllibrary)  [file join $conf(${server},root) "tcl"]
    }
    if ![info exists conf(${server},directoryfile)] {
	set conf(${server},directoryfile)  $directoryfile
    }
    if ![info exists conf(${server},modules)] {
	set conf(${server},modules)  $modulelist
    }
    if ![info exists conf(${server},debug)] {
	set conf(${server},debug)  $debug
    }

    # nsldap module
    # if a DefaultPool is specified, set defaults
    if [info exists conf(${server},ldapDefaultPool)] {
	if ![info exists conf(${server},ldapPools)] {
	    set conf(${server},ldapPools)  "*"
	}
    }

    # tDAV module
    if [info exists conf($server,shares)] {
	# We have shares, so we have to check the OPTIONS
	foreach share $conf($server,shares) {
	    if ![info exists conf($server,$share,dav_options)] {
		set conf($server,$share,dav_options) \
		    "OPTIONS COPY GET PUT MOVE DELETE HEAD MKCOL \
                     POST PROPFIND PROPPATCH LOCK UNLOCK"
	    }
	}
    }

    # priority of configuration file:
    #    1- config parameter in domains.cfg
    #    2- file with name ${server}.tcl
    #    3- default file: server.tcl

    if ![info exists conf(${server},config)] {
	if [file exists [conffile ${server}.tcl]] {
	    set conf(${server},config) [conffile ${server}.tcl]
	} else {
	    set conf(${server},config) [libfile server.tcl]
	}
    }
    # cgi configuration file, priority
    #    1- config parameter in domains.cfg
    #    2- file with name ${server}.cgi
    #    3- dont use.
    if [info exists conf(${server},config_cgi)] {
	if ![file exists [conffile $conf(${server},config_cgi)]] {
	    $ns_log fatal "nsd: $conf(${server},config_cgi) does not exist,"
	    $ns_log fatal "nsd: while looking for config_cgi of $server."
	    exit 1
	}
    } elseif [file exists [conffile ${server}.cgi]] {
	set conf(${server},config_cgi) [conffile ${server}.cgi]
	
    }

    # db configuration file, priority
    #    1- config parameter in domains.cfg
    #    2- file with name ${server}.db
    #    3- if database is specified, load default config.
    #
    # if database is not specified, this is all gratuitous
    #
    if [info exists conf(${server},config_db)] {
	if ![file exists [conffile $conf(${server},config_db)]] {
	    $ns_log fatal "nsd: $conf(${server},config_db) does not exist,"
	    $ns_log fatal "nsd: while looking for config_db of $server."
	    exit 1
	}
    } elseif [file exists [conffile ${server}.db]] {
	set conf(${server},config_db) [conffile ${server}.db]
    } elseif [info exists conf(${server},database)] {
    	set conf(${server},config_db) [libfile database.tcl]
    }

    # ssl configuration file, priority
    #    1- config parameter in domains.cfg
    #    2- file with name ${server}.ssl
    #    3- if bindssl is true in domains.cfg
    #       load default config.
    #
    if [info exists conf(${server},config_ssl)] {
	if ![file exists [conffile $conf(${server},config_ssl)]] {
	    $ns_log fatal "nsd: $conf(${server},config_ssl) does not exist,"
	    $ns_log fatal "nsd: while looking for config_ssl of $server."
	    exit 1
	}
    } elseif [file exists [conffile ${server}.ssl]] {
	set conf(${server},config_ssl) [conffile ${server}.ssl]
    } elseif [info exists conf(${server},httpsaddress)] {
    	set conf(${server},config_ssl) [libfile ssl.tcl]
    }

    if $conf(${server},skip) {
	$ns_log notice "nsd: skipping ${server} configuration."
    } else {
	$ns_log notice "nsd: ${server} configuration, reading: $conf(${server},config):"
	source $conf(${server},config)
	$ns_log notice "nsd: done ${server} configuration."
    }
}
#
$ns_log notice "nsd: Main server configuration"

#
# GLOBAL CONFIGURATION
#

$ns_section "ns/parameters"
$ns_param home ${homedir}

$ns_param user  www-data
$ns_param group www-data

# Data structures
$ns_param   dstringcachemaxentries 10        ;# Max no. of Dstrings to put on cache
$ns_param   dstringcachemaxsize    [expr 3*1024]
$ns_param   iobufsize              16000     ;# Buffer size suitable for I/O

# Limits
$ns_param   keepalivetimeout 30       ;# Max time conn is kept alive (keepalive)
;#   (set to 0 to disable keepalive)
$ns_param   listenbacklog   32        ;# Max length of pending conn queue
$ns_param   maxkeepalive    100       ;# Max no. of conns in keepalive state
$ns_param   schedmaxelapsed 2         ;# Warn when waiting on really long procs
$ns_param   shutdowntimeout 20        ;# Secs to wait on shutdown if open conns

# Server logging
$ns_param dev             true      ;# Display logging with "Dev" severity
$ns_param debug           $debug     ;# Display logging with "Debug" severity
$ns_param logexpanded     false     ;# true = double-spaced server.log
$ns_param logroll         false     ;# Roll server.log every 24 hours.
$ns_param maxbackup       10        ;# Max number of old server.log files

$ns_param serverlog       [logfile error.log]	;# Logging file name
$ns_param pidfile         [file join ${piddir} ${package}.pid]	;# pid of server file name

# DNS tuning
$ns_param   dnscache        true      ;# In-memory cache of DNS lookups
$ns_param   dnscachetimeout 60        ;# How long to keep hostnames in cache

# Miscellaneous
$ns_param   checkexitcode   false     ;# Check exit code on forked process
$ns_param   crashcmd        ns_crash  ;# A Tcl command that dumps core.
$ns_param   mailhost        localhost ;# SMTP host for ns_sendmail

# Character set Encoding
$ns_param   outputCharset      iso-8859-1
$ns_param   HackContentType    true

#
# Thread library (nsthread) parameters
#
$ns_section "ns/threads"
$ns_param   mutexmeter      true      ;# measure lock contention
$ns_param   stacksize       [expr $stack*1024]  ;# stack size per thread (in bytes)

# MIME types.
#
$ns_section "ns/mimetypes"
$ns_param   default         "*/*"     ;# MIME type for unknown extension
$ns_param   noextension     "*/*"     ;# MIME type for missing extension
#$ns_param   ".xls"          "application/vnd.ms-excel"

#   I18N Mime-types; define content-type header values
#                    to be mapped from these file-types.
#                    Note that you can map file-types of adp files to control
#                    the output encoding through mime-type specificaion.
#                    Remember to add an adp mapping for that extension.
#
$ns_param   .adp            "text/html; charset=iso-8859-1"
$ns_param   .u_adp          "text/html; charset=UTF-8"
$ns_param   .gb_adp         "text/html; charset=GB2312"
$ns_param   .sjis_html      "text/html; charset=shift_jis"
$ns_param   .sjis_adp       "text/html; charset=shift_jis"
$ns_param   .gb_html        "text/html; charset=GB2312"

#   I18N File-type to Encoding mappings
#
$ns_section "ns/encodings"
$ns_param   .utf_html       "utf-8"
$ns_param   .sjis_html      "shiftjis"
$ns_param   .gb_html        "gb2312"
$ns_param   .big5_html      "big5"
$ns_param   .euc-cn_html    "euc-cn"

#
# Note: you will need to include file-type to encoding mappings
#       for ANY source files that are to be used, to allow the
#       server to handle them properly.  E.g., the following
#       asserts that the GB-producing .adp files are themselves
#       encoded in GB2312 (this is not simply assumed).
#
$ns_param   .gb_adp         "gb2312"

#
# nsldap Module
#

if [info exists ldappools] {
    foreach pool $ldappools {
	
	# set default values
	if ![info exists ldap($pool,connections)] {
	    set ldap($pool,connections) 1
	}
	if ![info exists ldap($pool,verbose)] {
	    set ldap($pool,verbose) $debug
	}
	
	$ns_section "ns/ldap/pool/${pool}"
	$ns_param user        $ldap($pool,user)
	$ns_param password    $ldap($pool,password)
	$ns_param host        $ldap($pool,host)
	$ns_param connections $ldap($pool,connections)
	$ns_param verbose     $ldap($pool,verbose)
    }
    $ns_section "ns/ldap/pools"
    foreach pool $ldappools {
	$ns_param ldap $pool
    }
}

#
# Web based stats interface.
#
$ns_section ns/server/stats
if ![info exists stats] { set stats false }
$ns_param enabled $stats
if [info exists stats_url]      { $ns_param url $stats_url }
if [info exists stats_user]     { $ns_param user $stats_user }
if [info exists stats_password] { $ns_param password $stats_password }

$ns_section ns/module/nssock
$ns_param port            $conf(${defaultserver},httpport)
$ns_param hostname        $conf(${defaultserver},hostname)
$ns_param address         $conf(${defaultserver},address)
$ns_param defaultserver   $defaultserver


$ns_section "ns/interps/CGIinterps" 
$ns_param .pl  "/usr/bin/perl"
# php wrapper hack
if [info exists php_wrapper] {
    $ns_param .php $php_wrapper
}

$ns_section ns/modules
$ns_param nssock     nssock.so
