/source/core/server/src/nanoweb.php
PHP | 3130 lines | 2393 code | 645 blank | 92 comment | 292 complexity | fa2926a73f2e0f3d89540af96d45b6c3 MD5 | raw file
Possible License(s): BSD-3-Clause, AGPL-1.0, GPL-3.0
- #!/usr/local/bin/php -q
- <?php
- /*
- Nanoweb, the aEGiS PHP web server
- =================================
- Copyright (C) 2002-2005 Vincent Negrier aka. sIX <six@aegis-corp.org>
- 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 2, or (at your option)
- any later version.
- 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, write to the Free Software
- Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
- error_reporting(E_PARSE | E_ERROR);
- if (strpos($opts='^'.implode('_', $_SERVER["argv"]).'$', "--debug") + strpos($opts, "--verbose")) { error_reporting(E_ALL); }
- define("VERSION", "2.2.9");
- // Hard configuration and defaults
- define("DEFAULT_CONFIG_FILE", (((strpos(strtoupper(PHP_OS), "WIN")===0) || (strpos(strtoupper(PHP_OS), "CYGWIN")===0))?"C:\\nanoweb\\":"/etc/nanoweb/")."nanoweb.conf");
- define("DEFAULT_LISTEN_ADDR", "0.0.0.0");
- define("DEFAULT_LISTEN_PORT", 80);
- define("DEFAULT_LISTEN_QUEUE", 20);
- define("DEFAULT_MIMETYPES", "/etc/mime.types");
- define("DEFAULT_CONTENT_TYPE", "text/plain");
- define("DEFAULT_REQUEST_TIMEOUT", 15);
- define("DEFAULT_ACCESS_FILE", ".nwaccess");
- define("DEFAULT_DOCROOT", "./");
- define("DEFAULT_LOGFILE", "./access.log");
- define("DEFAULT_LOGTYPE", "combined");
- define("DEFAULT_FBWELCOMEFILE", ".welcome");
- define("DEFAULT_STATIC_BUFFER_SIZE", 1048576);
- define("DEFAULT_CONTENT_HANDLER", "static");
- define("DEFAULT_MAX_SERVERS", 25);
- define("DEFAULT_ACCESS_POLICY", "override");
- define("DEFAULT_SERVER_THEME", "default");
- define("DEFAULT_SERVER_LANG", "en-us");
- define("SCK_WRITE_PACKET_SIZE", 8192);
- define("SCK_READ_PACKET_SIZE", 4096);
- define("SCK_READ_SELECT_TIMEOUT", 2);
- define("SCK_MAX_STALL_TIME", 60);
- define("SPM_CACHES_LIFETIME", 15);
- define("HTTP_VERSION", "HTTP/1.1");
- define("SERVER_STRING", "aEGiS_nanoweb");
- define("SERVER_STRING_V", SERVER_STRING."/".VERSION);
- define("INT_MSGSIZE", 4096);
- define("NM_HIT", " HIT");
- define("NM_RESTART_LOGGERS", "LGRST");
- define("NM_SERVER_STATE", "SRVST");
- define("NM_RELOAD_THEME", "RLTHM");
- define("NM_BLOCK_IP", "BANIP");
- define("NM_UNBLOCK_IP", "DBNIP");
- define("NW_BAD_OUTSIDE_DOCROOT", 1);
- define("NW_BAD_DOT_FILE", 2);
- define("NW_BAD_WIN_DEVICE", 3);
- define("NW_SB_STATUS", 0);
- define("NW_SB_PEERHOST", 1);
- define("NW_SB_FORKTIME", 2);
- define("NW_EL_DEBUG", 1);
- define("NW_EL_HIT", 2);
- define("NW_EL_NOTICE", 4);
- define("NW_EL_BLOCKING", 8);
- define("NW_EL_WARNING", 16);
- define("NW_EL_ERROR", 32);
- define("NW_EL_ALL", 255);
- define("NW_EL_DEFAULT", NW_EL_NOTICE | NW_EL_BLOCKING | NW_EL_WARNING | NW_EL_ERROR);
- define("NW_TMPL_SIGNATURE", "server_signature");
- define("NW_TMPL_ERROR_PAGE", "error_page");
- define("NW_TMPL_ERROR_RESOURCE", "error_resource");
- define("NW_TMPL_ERROR_ADMIN", "error_admin");
- define("REQUIRED_PHP_VERSION", "4.2.0");
- // Internally used global vars
- $HTTP_HEADERS=array(100 => "100 Continue",
- 200 => "200 OK",
- 201 => "201 Created",
- 204 => "204 No Content",
- 206 => "206 Partial Content",
- 300 => "300 Multiple Choices",
- 301 => "301 Moved Permanently",
- 302 => "302 Found",
- 303 => "303 See Other",
- 304 => "304 Not Modified",
- 307 => "307 Temporary Redirect",
- 400 => "400 Bad Request",
- 401 => "401 Unauthorized",
- 403 => "403 Forbidden",
- 404 => "404 Not Found",
- 405 => "405 Method Not Allowed",
- 406 => "406 Not Acceptable",
- 408 => "408 Request Timeout",
- 410 => "410 Gone",
- 413 => "413 Request Entity Too Large",
- 414 => "414 Request URI Too Long",
- 415 => "415 Unsupported Media Type",
- 416 => "416 Requested Range Not Satisfiable",
- 417 => "417 Expectation Failed",
- 500 => "500 Internal Server Error",
- 501 => "501 Method Not Implemented",
- 503 => "503 Service Unavailable",
- 506 => "506 Variant Also Negotiates");
- $TEST_FUNCS=array( "pcntl_fork" => false,
- "socket_create" => true,
- "posix_setuid" => false,
- "gzencode" => false);
- $conf_defaults=array( "listeninterface" => DEFAULT_LISTEN_ADDR,
- "listenport" => DEFAULT_LISTEN_PORT,
- "listenqueue" => DEFAULT_LISTEN_QUEUE,
- "mimetypes" => DEFAULT_MIMETYPES,
- "requesttimeout" => DEFAULT_REQUEST_TIMEOUT,
- "accessfile" => DEFAULT_ACCESS_FILE,
- "documentroot" => DEFAULT_DOCROOT,
- "log" => DEFAULT_LOGFILE,
- "logtype" => DEFAULT_LOGTYPE,
- "fbwelcomefile" => DEFAULT_FBWELCOMEFILE,
- "defaultcontenttype" => DEFAULT_CONTENT_TYPE,
- "staticbuffersize" => DEFAULT_STATIC_BUFFER_SIZE,
- "defaulthandler" => DEFAULT_CONTENT_HANDLER,
- "maxservers" => DEFAULT_MAX_SERVERS,
- "accesspolicy" => DEFAULT_ACCESS_POLICY,
- "servertheme" => DEFAULT_SERVER_THEME);
- $conf_vhosts_propagate=array( "documentroot",
- "directoryindex",
- "serveradmin",
- "user",
- "group",
- "logdir",
- "log",
- "logtype",
- "filebrowser",
- "fbshowdotfiles",
- "fbwelcomefile",
- "userdir",
- "ignoredotfiles",
- "allowsymlinkto",
- "maxrequestbodylength",
- "maxrequesturilength");
- // Needed as long as PHP filetype() is broken on win32
- $win_devices=array("nul", "con", "aux", "prn", "clock$", "com1", "com2", "com3", "com4", "com5", "com6", "com7", "com8", "lpt1", "lpt2", "lpt3", "lpt4", "lpt5", "lpt6", "lpt7", "lpt8");
- // Command line help page
- $cmdline_help=<<<EOT
- Usage: nanoweb.php [/path/to/nanoweb.conf] [options]
- nanoweb supports the following command line options :
- --help -h : this help screen
- --version -v : show version info
- --config=/path/to/nanoweb.conf -c : configuration file
- --set-option="optionname=optionvalue" -o : set configuration option
- --add-option="optionname=optionvalue" -a : add configuration option
- --start-daemon -d : start nanoweb and run in background
- --config-test -t : test configuration and exit
- --quiet -q : don't send text to console
- EOT;
- // Static response class
- class static_response {
- var $content_length;
- function static_response($str) {
- $this->str=$str;
- $this->content_length=strlen($str);
-
- }
- function parser_open($args, $filename, &$rq_err, &$cgi_headers) {
- }
- function parser_get_output() {
- $s=$this->str;
- $this->str="";
- return($s);
- }
- function parser_eof() {
- return($this->str === "");
-
- }
- function parser_close() {
- }
- }
- $null_response =& new static_response("");
- $lf=$null_response;
- // Functions
- function _parseconfig_close_part(&$conf, $cpart, $nodefaults=false) {
- if (!$conf[$cpart]["_nw_pcp"]) {
-
- if (!$nodefaults) {
-
- if ($cpart=="global") {
-
- // Use default values for the global config scope
-
- foreach ($GLOBALS["conf_defaults"] as $key=>$dval) if (!isset($conf[$cpart][$key])) $conf[$cpart][$key][0]=$dval;
- } else {
- // Propagate appropriate directives to vhosts
- foreach ($GLOBALS["conf_vhosts_propagate"] as $key=>$pkey) if (!isset($conf[$cpart][$pkey])) $conf[$cpart][$pkey]=$conf["global"][$pkey];
- if (!$conf[$cpart]["servername"]) $conf[$cpart]["servername"][]=$cpart;
- }
-
- }
-
- // Transform some directives (Dir = Idx Value)
-
- foreach (array("parseext", "errordocument", "errorheader") as $dir) {
-
- if ($conf[$cpart][$dir]) {
- foreach ($conf[$cpart][$dir] as $ps) {
- $ext=strtolower(strtok($ps, " "));
- $dext=trim(strtok(""));
-
- $conf[$cpart]["_".$dir]["_".$ext]=$dext;
- }
-
- }
- }
-
- $conf[$cpart]["_nw_pcp"]=true;
-
- }
- }
- function _parseconfig_parse_line($str) {
- $cnfl=array();
- ereg("([^ =\n\t]+)[ \t]*=?[ \t]*([^\n]+)", $str, $cnfl);
- return(array(strtolower(trim($cnfl[1])), trim($cnfl[2])));
- }
- function parseconfig($conf_arr, $nodefaults=false) {
- $cpart="global";
- $_pcp=array("global");
- $included_confs[$GLOBALS["conffile"]]=true;
-
- if ($clen=count($conf_arr)) {
-
- // Pass 1 (build the $conf_arr array)
- $key=-1;
-
- while ($key++<=$clen) {
- $str=$conf_arr[$key];
-
- list($cnfk, $cnfv)=_parseconfig_parse_line($str);
- if ($cnfk=="configdir") {
- $confdir=$cnfv;
-
- } else if ($cnfk=="include") {
- $ifn=($confdir?($confdir.DIRECTORY_SEPARATOR):"").$cnfv;
- if (!@is_readable($ifn)) $ifn=$cnfv;
-
- if ($included_confs[$ifn]) {
- $conf_err="configuration includes loop detected line ".$key." : '".trim($str)."'";
- break;
-
- }
-
- if (!@is_readable($ifn)) {
- $conf_err="unable to include configuration file line ".$key." : '".$ifn."'";
- break;
-
- }
- $subconf_arr=file($ifn);
- $conf_arr=array_merge(array_slice($conf_arr, 0, $key), $subconf_arr, array_slice($conf_arr, $key+1));
- $key=-1;
- $clen=count($conf_arr);
- $included_confs[$ifn]=true;
-
- }
- }
- // Pass 2 (build the $conf array)
-
- foreach ($conf_arr as $key=>$str) {
- switch ($str[0]) {
- case "#":
- case ";":
- case "\n":
- case "":
- break;
-
- case "[":
- if ($cpart!="global") $_pcp[]=$cpart;
-
- $cpart=substr(trim($str), 1, -1);
- if ($cpart{0}=="/") $cpart="global";
- if ($cpart!="global") unset($conf[$cpart]);
-
- break;
- default:
- list($cnfk, $cnfv)=_parseconfig_parse_line($str);
- switch ($cnfk) {
- case "documentroot":
-
- $rp=nw_realpath($cnfv);
- if (!($rp && @is_dir($rp))) {
-
- $conf_err="directory not found at line ".$key." : '".trim($str)."'";
- unset($conf[$cpart]);
- $cpart="_err:".$cpart;
- }
-
- if (substr($rp, -1)!=DIRECTORY_SEPARATOR) $rp.=DIRECTORY_SEPARATOR;
- $conf[$cpart][$cnfk][]=$rp;
- break;
- case "serveralias":
- if ($cnfv!=$cpart) $conf[$cnfv]=&$conf[$cpart];
- break;
-
- case "alias":
- $conf[$cpart][$cnfk][]=$cnfv;
- $aliases=explode(" ", $cnfv);
- $conf[$cpart]["_aliases"][$aliases[0]]=$aliases[1];
- break;
-
- case "serverlog":
- $lname=strtok($cnfv, " ");
-
- if ($lmode=strtok("")) {
- $lbmode=0;
- foreach($GLOBALS["srvlog_levels"] as $lvl=>$bin_lvl) if (strpos($lmode, $lvl)!==false) $lbmode|=$bin_lvl;
- foreach($GLOBALS["srvlog_levels"] as $lvl=>$bin_lvl) if (strpos($lmode, "-".$lvl)!==false) $lbmode&=~$bin_lvl;
- } else {
-
- $lbmode=NW_EL_DEFAULT;
- }
-
- $conf[$cpart]["_serverlog"][$lname]=$lbmode;
-
- break;
- case "loadtheme":
- $conf[$cpart][$cnfk][]=$cnfv;
- $conf[$cpart]["servertheme"][]=$cnfv;
- break;
- default:
- $conf[$cpart][$cnfk][]=$cnfv;
- break;
- }
- break;
- }
-
- }
- }
-
- // Pass 3 (close all $conf sections)
-
- if ($cpart!="global") $_pcp[]=$cpart;
-
- foreach ($_pcp as $clpart) _parseconfig_close_part($conf, $clpart, $nodefaults);
- return($conf_err?$conf_err:$conf);
- }
- function cmdline_conf_upd($conf, $cmdline_conf_overrides, $cmdline_conf_adds) {
- foreach ($cmdline_conf_overrides as $cs) {
- $ca=explode("=", $cs);
- $conf["global"][strtolower($ca[0])]=array($ca[1]);
- }
- foreach ($cmdline_conf_adds as $cs) {
- $ca=explode("=", $cs);
- $conf["global"][strtolower($ca[0])][]=$ca[1];
- }
- return($conf);
- }
- function load_modules($conf) {
- global $mod_tokens;
-
- $mod_tokens=array();
-
- if ($lm_arr=$conf["global"]["loadmodule"]) foreach ($lm_arr as $key=>$modname) {
- $clsname=basename($modname, ".php");
-
- if (!is_file($modname)) {
- foreach (access_query("modulesdir") as $md) if (is_file($md.DIRECTORY_SEPARATOR.$modname)) {
- $moddir=$md;
- break;
-
- }
-
- } else $moddir="";
-
- if (!$ld_clss[$clsname]) {
-
- $nload=(!class_exists($clsname));
-
- // Try to load with given path
-
- @include_once($modname);
- $modloaded=class_exists($clsname);
- if (!$modloaded) {
- // And try with modulesdir if not found
- @include_once($moddir.$modname);
- $modloaded=class_exists($clsname);
-
- }
- if ($modloaded) {
-
- $ld_clss[$clsname]=true;
- $tmp=&new $clsname;
- $modules[$tmp->modtype][]=&$tmp;
- $tmp_modlist[]=array($clsname, $tmp->modname);
- if (is_array($tmp->urls)) foreach ($tmp->urls as $url) $modules["url:".$url]=&$tmp;
- if (is_array($tmp->methods)) foreach ($tmp->methods as $method) $modules["method:".$method]=&$tmp;
- if (is_string($mt=$tmp->sig_token)) $mod_tokens[$tmp->modname]=$mt;
- if ($nload) techo("loaded module : ".$tmp->modname);
- } else {
- techo("WARN: unable to load module '".$modname."'", NW_EL_WARNING);
-
- }
-
- }
-
- }
- $GLOBALS["stats_modlist"]=$tmp_modlist;
- return ($modules);
- }
- function load_theme($themefname, $load_notice=false, $reload=false) {
- $tfn=($GLOBALS["conf"]["global"]["configdir"][0]?($GLOBALS["conf"]["global"]["configdir"][0].DIRECTORY_SEPARATOR):"").$themefname;
- if (!@is_readable($tfn)) $tfn=$themefname;
-
- if ($thmarr=@file($tfn)) {
- $ts=0;
-
- foreach ($thmarr as $thml) {
- if (strtolower(rtrim($thml))=="[/".$thm_sc."]") {
- $theme[$thm_sc]=substr($theme[$thm_sc], 0, -1);
- --$ts;
- $thm_sc="";
-
- } else if (($thml{0}=="[") && (substr(rtrim($thml), -1)=="]")) {
- $thm_sc=strtolower(substr(rtrim($thml), 1, -1));
- } else if ($thm_sc) {
- $theme[$thm_sc].=$thml;
- $ts+=strlen($thml);
-
- }
- }
- if ($theme["theme_id"]) {
- if (!$theme["theme_name"]) $theme["theme_name"]=$theme["theme_id"];
- $theme["theme_id"]=trim($theme["theme_id"]);
- $theme["theme_name"]=trim($theme["theme_name"]);
-
- $theme["theme_language"]=trim($theme["theme_language"])
- or $theme["theme_language"]=DEFAULT_SERVER_LANG;
- if ($load_notice) techo(($reload?"re":"")."loaded theme : ".$theme["theme_name"]." (".$ts." bytes)");
- } else {
- techo("WARN: invalid theme file '".$tfn."'", NW_EL_WARNING);
-
- }
- clearstatcache();
- $theme["_fname"]=$tfn;
- $theme["_mtime"]=filemtime($tfn);
- $theme["_pmode"]=$GLOBALS["pmode"];
-
- } else {
- techo("WARN: unable to load theme file '".$tfn."'", NW_EL_WARNING);
-
- }
- return($theme);
- }
- function load_themes($conf) {
- if (is_array($conf["global"]["loadtheme"])) foreach ($conf["global"]["loadtheme"] as $themefname) {
- $theme=load_theme($themefname, true);
- $themes[$theme["theme_id"]]=$theme;
- $themes[$theme["_fname"]]=$theme;
-
- } else {
- techo("WARN: 'LoadTheme' directive not found in config file", NW_EL_WARNING);
-
- }
- return($themes);
- }
- function modules_init($method="init") {
- global $modules;
-
- foreach ($modules as $modclass) if (is_array($modclass)) {
-
- for ($a=0;$a<count($modclass);$a++) {
-
- if ((method_exists($modclass[$a], $method)) && (!$modinit[$mc=get_class($modclass[$a])])) {
-
- $modclass[$a]->$method();
- $modinit[$mc]=true;
- }
- }
-
- } else {
- if ((method_exists($modclass, $method)) && (!$modinit[$mc=get_class($modclass)])) {
-
- $modclass->$method();
- $modinit[$mc]=true;
- }
- }
- }
- function load_access_files($dir, &$access, $rec=0) {
- global $conf, $access_cache;
- if (is_array($z=$access_cache[$dir])) {
- // Access cache hit
-
- $access=$z;
- return;
-
- } else {
-
- // Access cache miss
-
- if (!$rec) $access=array();
-
- $ndir=substr($dir, 0, strrpos($dir, DIRECTORY_SEPARATOR));
- $cont = false;
- $r_mdir = nw_realpath($ndir.DIRECTORY_SEPARATOR);
- $cont_dirs = array(nw_realpath($GLOBALS["docroot"]));
- foreach ($conf[$GLOBALS["vhost"]]["allowsymlinkto"] as $als) $cont_dirs[] = nw_realpath($als);
-
- foreach ($cont_dirs as $cdir) if (strpos($r_mdir, $cdir)===0) {
-
- load_access_files($ndir, $access, $rec+1);
- break;
- }
-
- $afn=$dir.DIRECTORY_SEPARATOR.$conf["global"]["accessfile"][0];
- if (is_readable($afn) && ($accesstmp=@file($afn)) && ($tmp_access=parseconfig($accesstmp, true))) foreach ($tmp_access as $key=>$val_arr) {
-
- foreach ($val_arr as $ckey=>$cval_arr) {
-
- $ap=$GLOBALS["access_policy"][$ckey] or
- $ap=$conf["global"]["accesspolicy"][0];
- switch ($ap) {
- case "override":
- $access[$key][$ckey]=$cval_arr;
- break;
- case "merge":
- $access[$key][$ckey]=array_merge($access[$key][$ckey], $cval_arr);
- break;
- }
- }
- if (!$rec) break;
-
- }
- $access_cache[$dir]=$access;
-
- }
- }
- function access_query($key, $idx=false) {
- global $access, $conf;
- $ap=$GLOBALS["access_policy"][$key] or
- $ap=$conf["global"]["accesspolicy"][0];
- switch ($ap) {
- case "override":
- $tmp=$access["global"][$key] or
- $tmp=$conf[$GLOBALS["vhost"]][$key] or
- $tmp=$conf["global"][$key];
- break;
- case "merge":
- $tmp=array_merge($conf["global"][$key] ? $conf["global"][$key] : array(), $conf[$GLOBALS["vhost"]][$key] ? $conf[$GLOBALS["vhost"]][$key] : array(), $access["global"][$key] ? $access["global"][$key] : array());
- break;
- }
- if ($idx===false) {
- return($tmp);
- } else {
- return($tmp[$idx]);
-
- }
- }
- function core_modules_hook($hname) {
- if ($mh_arr=&$GLOBALS["modules"]["core_".$hname]) foreach (array_keys($mh_arr) as $a) $mh_arr[$a]->main();
- }
- function log_ids() {
- global $conf;
-
- if ($setgid=@posix_getgrnam($conf["global"]["loggergroup"][0])) $g=$setgid["gid"];
- else if ($setgid=@posix_getgrnam($conf["global"]["group"][0])) $g=$setgid["gid"];
- if ($setuid=@posix_getpwnam($conf["global"]["loggeruser"][0])) $u=$setuid["uid"];
- else if ($setuid=@posix_getpwnam($conf["global"]["user"][0])) $u=$setuid["uid"];
- return(array("uid" => $u, "gid" => $g));
- }
- function log_srv($str, $loglevel=NW_EL_NOTICE) {
- if ($srvlog_arr=$GLOBALS["conf"]["global"]["_serverlog"]) foreach ($srvlog_arr as $s=>$bmode) if ($loglevel & $bmode) {
-
- if (($GLOBALS["pmode"]=="master") && (!file_exists($s))) $chown=true;
-
- if ($sl=@fopen($s, NW_BSAFE_APP_OPEN)) {
- fputs($sl, $str);
- fclose($sl);
-
- }
- if ($chown && $GLOBALS["posix_av"] && ($lids=log_ids())) {
- chgrp($s, $lids["gid"]);
- chown($s, $lids["uid"]);
- }
- }
- }
- function nw_gethostbyaddr($ip) {
- static $ns_lastreq;
-
- if ($ip != $ns_lastreq[0]) {
-
- $hostname = @gethostbyaddr($ip);
- $fwr_ip = @gethostbyname($hostname);
- if ($ip != $fwr_ip) {
-
- // Inconsistent DNS data
-
- $hostname = $ip;
- }
-
- $ns_lastreq = array($ip, $hostname);
- }
- return($ns_lastreq[1]);
- }
- function nw_realpath($dir) {
- global $rp_cache;
-
- if ($rp=$rp_cache[$dir]) {
- return($rp);
-
- } else {
- return($rp_cache[$dir]=realpath($dir));
-
- }
- }
- function nw_server_string() {
- switch (strtolower(access_query("serversignature", 0))) {
- case "fake": return(access_query("serverfakesignature", 0));
- case "off": return("");
- case "prod": return(SERVER_STRING);
- case "min": return(SERVER_STRING_V);
- case "os": return(SERVER_STRING_V." (".PHP_OS.")");
- case "php": return(SERVER_STRING_V." (".PHP_OS."; PHP/".phpversion().")");
- case "full":
- default:
- return(SERVER_STRING_V." (".PHP_OS."; PHP/".phpversion().($GLOBALS["mod_tokens"]?"; ":"").implode("; ", $GLOBALS["mod_tokens"]).")");
- }
-
- }
- function _genpage_signature() {
- return(nw_apply_template(NW_TMPL_SIGNATURE, array("server_string" => nw_server_string(), "server_name" => $GLOBALS["conf"][$GLOBALS["vhost"]]["servername"][0]), true));
-
- }
- function nw_apply_template($template, $args, $no_add=false) {
- global $themes;
-
- $sts = access_query("servertheme");
- $lts = access_query("loadtheme");
-
- $thmid=array_pop($sts);
- $fname=$themes[$thmid]["_fname"];
-
- if ($thmid==$fname) $thmid=$themes[$thmid]["theme_id"];
- if ((!is_array($themes[$thmid])) && ($ltid=array_pop($lts))) $fname=$ltid;
-
- clearstatcache();
-
- if (($themes[$thmid]["_mtime"]!=filemtime($fname)) && ($tmp_thm=load_theme($fname))) {
- if ($themes[$thmid]["_pmode"]=="master") int_sendtomaster(NM_RELOAD_THEME, $thmid);
- $themes[$thmid]=$tmp_thm;
- $themes[$fname]=$tmp_thm;
- $themes[$tmp_thm["_fname"]]=$tmp_thm;
- }
- $tlang=strtolower($themes[$thmid]["theme_language"]);
- if (($al=$GLOBALS["htreq_headers"]["ACCEPT-LANGUAGE"]) && ($als=nw_decode_mq_hdr($al))) {
- foreach (array_keys($als) as $lang) {
-
- $lang=strtolower($lang);
-
- if (isset($themes[$thmid][$template.":".$lang])) {
- $tname=$template.":".$lang;
- break;
-
- } else if ($tlang==$lang) {
- break;
-
- }
- }
- }
- if (!$tname) $tname=$template;
-
- $tmpl=$themes[$thmid][$tname] or
- $tmpl=$themes[DEFAULT_SERVER_THEME][$tname];
- foreach ($args as $k=>$v) $tr_arr["@$".strtolower($k)."@"]=$v;
- if (!$no_add) $tr_arr['@$server_signature@']=_genpage_signature();
- $trt=strtr($tmpl, $tr_arr);
- while ((($p=strpos($trt, "@!"))!==false) && (($p2=strpos(substr($trt, $p+2), "@"))!==false)) {
- $ret=substr($trt, 0, $p);
- $ret.=access_query(strtolower(substr($trt, $p+2, $p2)), 0);
- $ret.=substr($trt, $p+$p2+3);
- $trt=$ret;
- }
- return($trt);
- }
- function nw_server_vars($include_cgi_vars=false) {
- global $conf;
-
- $filename=$GLOBALS["docroot"].$GLOBALS["http_uri"];
-
- $nsv["SERVER_SOFTWARE"]=nw_server_string();
- $nsv["SERVER_NAME"]=$conf[$GLOBALS["vhost"]]["servername"][0];
- $nsv["SERVER_PROTOCOL"]=HTTP_VERSION;
- $nsv["SERVER_PORT"]=$GLOBALS["lport"];
- $nsv["SERVER_ADDR"]=$conf["global"]["listeninterface"][0];
- $nsv["SERVER_API"]=VERSION;
- $nsv["SERVER_ADMIN"]=$conf[$GLOBALS["vhost"]]["serveradmin"][0];
- $nsv["REQUEST_METHOD"]=$GLOBALS["http_action"];
- $nsv["PATH_TRANSLATED"]=$nsv["SCRIPT_FILENAME"]=nw_realpath($filename);
- $nsv["SCRIPT_NAME"]="/".$GLOBALS["docroot_prefix"].$GLOBALS["http_uri"];
- $nsv["QUERY_STRING"]=$GLOBALS["query_string"];
- $nsv["REMOTE_HOST"]=$GLOBALS["remote_host"];
- $nsv["REMOTE_ADDR"]=$GLOBALS["remote_ip"];
- $nsv["REMOTE_PORT"]=$GLOBALS["remote_port"];
- $nsv["AUTH_TYPE"]=$GLOBALS["auth_type"];
- $nsv["DOCUMENT_ROOT"]=$GLOBALS["docroot"];
- $nsv["REQUEST_URI"]="/".$GLOBALS["real_uri"].($nsv["QUERY_STRING"]?("?".$nsv["QUERY_STRING"]):"");
- $nsv["PATH_INFO"]=$GLOBALS["path_info"];
- if (($GLOBALS["logged_user"]) && ($GLOBALS["logged_user"] != " ")) {
- $nsv["REMOTE_USER"] = $GLOBALS["logged_user"];
- }
- if ($asv=access_query("addservervar")) foreach ($asv as $str) {
- $k=strtok($str, " ");
- $v=strtok("");
- if ($k) $nsv[$k]=$v;
-
- }
- if ($GLOBALS["add_nsv"]) foreach ($GLOBALS["add_nsv"] as $key=>$val) $nsv[$key]=$val;
- if ($include_cgi_vars && ($rq_hdrs=$GLOBALS["htreq_headers"])) foreach($rq_hdrs as $key=>$val) $nsv["HTTP_".str_replace("-", "_", $key)]=$val;
- return $nsv;
- }
- function nw_url_addslash($s) {
- $ret = strtok($s, "?")."/";
- if (($q = strtok("")) !== false) $ret .= "?".$q;
- return $ret;
- }
- function techo($s, $level=NW_EL_NOTICE, $flush=false) {
- global $conf;
- static $srv_buf;
-
- $tl=date("Ymd:His")." $s\n";
- if (!$conf["_complete"] && !$flush) {
- $srv_buf[]=array($tl, $level);
-
- } else {
-
- if (($conf["global"]["servermode"][0]!="inetd") && !$GLOBALS["quiet"]) {
- if ($srv_buf) foreach ($srv_buf as $sb_arr) echo $sb_arr[0];
- echo $tl;
- flush();
- }
- if ($srv_buf) {
-
- foreach ($srv_buf as $sb_arr) log_srv($sb_arr[0], $sb_arr[1]);
-
- $srv_buf=array();
- }
- log_srv($tl, $level);
- }
- }
- function errexit($s, $errno=-1) {
- global $pidfile, $start_daemon;
-
- $estr="FATAL: ".$s;
- techo($estr, NW_EL_ERROR, true);
- if ($pidfile) unlink($pidfile);
- if ($start_daemon && ($stderr=@fopen("php://stderr", "w"))) {
- fputs($stderr, $estr."\n");
- fclose($stderr);
- }
- exit($errno);
- }
- function url_to_absolute($url) {
- return("http://".$GLOBALS["conf"][$GLOBALS["vhost"]]["servername"][0].(($GLOBALS["lport"]!=80)?(":".$GLOBALS["lport"]):"").($url!="/"?"/":"").$url);
- }
- function loadfile($filename, $extension, &$rq_err, &$cgi_headers, $force_parser=false) {
-
- global $conf, $modules, $add_nsv;
-
- if (is_link($filename)) $filename=readlink($filename);
- chdir(dirname(nw_realpath($filename)));
- $filename=basename($filename);
- if (($parser=$force_parser) || ($parser=trim(access_query("_parseext", "_".strtolower($extension))))) {
- // Parsed content
-
- if (strpos($parser, " ")!==false) {
-
- $ps_type=strtok($parser, " ");
- $ps_arg=strtok("");
- if (strpos($ps_arg, '$')!==false) foreach (nw_server_vars() as $nkey=>$nval) $ps_arg=str_replace('$'.$nkey, $nval, $ps_arg);
- if (!$force_parser) {
- $add_nsv["REDIRECT_STATUS"]=$rq_err;
- $add_nsv["REDIRECT_URL"]="/".$GLOBALS["real_uri"];
- }
-
- } else $ps_type=$parser;
- } else {
- // Static content
- $ps_type=$conf["global"]["defaulthandler"][0];
- }
- if ($ps=$modules["parser_".$ps_type][0]) {
- if (is_object($rop=$ps->parser_open($ps_arg, $filename, $rq_err, $cgi_headers))) $ps=$rop;
- } else {
- $rq_err=500;
- $GLOBALS["add_errmsg"]="Unable to find an appropriate parser for this content type.<br><br>";
- $ps=$GLOBALS["null_response"];
-
- }
- return($ps);
- }
- function nw_host_to_vhost($host, $lport=80) {
-
- global $conf;
-
- // Try vhost=host:port
-
- if (is_array($conf[$phost=($host.":".$lport)])) return($phost);
-
- // Try vhost=host
-
- if (is_array($conf[$host])) return($host);
- // Try wildcards
- $hlen=strlen($host);
- for($vhlen=0;$vhlen<=$hlen;$vhlen++) {
-
- $whost="*".substr($host, $vhlen);
- if (is_array($conf[$phost=($whost.":".$lport)])) return($phost);
- if (is_array($conf[$whost])) return($whost);
- }
- // Or set to global
- return("global");
- }
- function nw_error_page($rq_err) {
-
- global $HTTP_HEADERS, $http_resource, $conf, $vhost, $add_errmsg;
-
- $err["error_code"]=$rq_err;
- $err["error_label"]=$HTTP_HEADERS[$rq_err];
- $err["error_add_message"]=$add_errmsg;
- $add_errmsg = "";
-
- $err["error_resource"]=($http_resource?(nw_apply_template(NW_TMPL_ERROR_RESOURCE, array("resource_name" => htmlentities($http_resource)), true)):"");
- if ($conf[$vhost]["serveradmin"][0]) $err["error_admin"]=nw_apply_template(NW_TMPL_ERROR_ADMIN, array("admin" => $conf[$vhost]["serveradmin"][0]), true);
-
- $err_page=nw_apply_template(NW_TMPL_ERROR_PAGE, $err) or
- $err_page="<html><head><title>".$HTTP_HEADERS[$rq_err]."</title></head><body><h1>".$HTTP_HEADERS[$rq_err]."</h1></body></html>";
- return($err_page);
- }
- function nw_use_chunked_encoding() {
- if (!isset($GLOBALS["lf"]->content_length) && $GLOBALS["keepalive"]) {
- if ($GLOBALS["http_version"]>="1.1") {
- return(true);
-
- } else {
- return("CLOSE");
-
- }
-
- } else return(false);
- }
- function nw_decode_mq_hdr($s) {
- if ($l=explode(",", $s)) foreach ($l as $e) {
- list($v, $q)=explode(";", $e);
- if ($q) list($d, $qn)=explode("=", $q);
- if (!$qn) $qn=1;
- if ($v) $r[$v]=$qn;
-
- }
- arsort($r);
- return($r);
- }
- function nw_allow_list($ext) {
-
- $tmp_marr=array();
- foreach ($GLOBALS["modules"] as $tmpmod) if (method_exists($tmpmod, "options")) if ($mod_methods=$tmpmod->options()) foreach ($mod_methods as $mod_method) if (!isset($tmp_marr[$mod_method])) $tmp_marr[$mod_method]=$mod_method;
-
- return ("GET, ".(access_query("_parseext", "_".strtolower($rq_file["extension"]))?"POST, ":"")."HEAD, OPTIONS".(count($tmp_marr)?", ":"").implode(", ", $tmp_marr));
- }
- function build_response_headers() {
- global $HTTP_HEADERS, $rq_err, $out_contenttype, $out_add_headers, $conf, $lf;
-
- if ($out_add_headers) {
-
- foreach ($out_add_headers as $key=>$val) switch (strtoupper($key)) {
-
- case "CONTENT-TYPE":
- $out_contenttype=$val;
- break;
- case "LOCATION":
- $rq_err=302;
- $add_headers.=$key.": ".$val."\r\n";
- break;
-
- case "COOKIES":
- foreach ($val as $cval) $add_headers.="Set-Cookie: ".$cval."\r\n";
- break;
- case "STATUS":
-
- $st=(int)strtok($val, " ");
- if ($stx=trim(strtok(""))) {
- $http_resp=$st." ".$stx;
-
- } else if ($stx=$HTTP_HEADERS[$st]) {
- $http_resp=$stx;
-
- } else {
- $http_resp=$st;
-
- }
- $rq_err=$st;
-
- break;
- default:
- $add_headers.=$key.": ".$val."\r\n";
-
- }
- }
-
- $clf=($GLOBALS["http_action"]=="HEAD"?$GLOBALS["hlf"]:$lf);
-
- $out_headers=HTTP_VERSION." ".($http_resp?trim($http_resp):$HTTP_HEADERS[$rq_err])."\r\n";
- $out_headers.="Date: ".gmdate("D, d M Y H:i:s T")."\r\n";
- if ($ss=nw_server_string()) $out_headers.="Server: ".$ss."\r\n";
- $out_headers.="Content-Type: ".$out_contenttype."\r\n";
- if ($ahlist=access_query("addheader")) foreach ($ahlist as $val) $out_headers.=trim($val)."\r\n";
- if (($rq_err>=400) && ($eh=access_query("_errorheader", "_".$rq_err))) $out_headers.=$eh."\r\n";
-
- $out_headers.=$add_headers;
- if ($GLOBALS["keepalive"]) {
-
- $out_headers.="Connection: Keep-Alive\r\n";
- $out_headers.="Keep-Alive: timeout=".(int)$conf["global"]["requesttimeout"][0].", max=".(int)($conf["global"]["keepalive"][0])."\r\n";
-
- } else {
-
- $out_headers.="Connection: close\r\n";
- }
-
- if ($GLOBALS["chunked"]) {
-
- $out_headers.="Transfer-Encoding: chunked\r\n";
- } else {
- if (is_int($clf->content_length)) $out_headers.="Content-Length: ".$clf->content_length."\r\n";
- }
- return($out_headers);
- }
- function nanoweb_init($conffile) {
- global $conf, $themes, $cmdline_conf_overrides, $cmdline_conf_adds, $modules, $posix_av, $pcntl_av, $gz_av, $mime, $access_policy, $sysusr, $sysgrp, $icnt, $banned_ips, $srvlog_levels;
-
- $dc=get_defined_constants();
- foreach ($dc as $cname=>$cval) if (substr($cname, 0, 6)=="NW_EL_") $srvlog_levels[strtolower(substr($cname, 6))]=$cval;
- $iconf=parseconfig(file($conffile));
- if (is_string($iconf)) {
- if ($icnt) {
-
- techo($iconf, NW_EL_WARNING);
- return(false);
- } else {
- errexit($iconf);
-
- }
-
- } else if (is_array($iconf)) {
- $conf=$iconf;
-
- }
- $conf=cmdline_conf_upd($conf, $cmdline_conf_overrides, $cmdline_conf_adds);
- $modules=load_modules($conf);
- modules_init();
- $themes=load_themes($conf);
- ++$icnt;
- $ap_aliases=array( "parseext" => "_parseext",
- "alias" => "_aliases",
- "errordocument" => "_errordocument",
- "errorheader" => "_errorheader" );
- $access_policy=array();
- foreach ($conf["global"]["accessoverride"] as $ov_dir) if ($ov_dir) $access_policy[strtolower($ov_dir)]="override";
- foreach ($conf["global"]["accessmerge"] as $mg_dir) if ($mg_dir) $access_policy[strtolower($mg_dir)]="merge";
- foreach ($conf["global"]["accessblock"] as $bl_dir) if ($bl_dir) $access_policy[strtolower($bl_dir)]="block";
- foreach ($ap_aliases as $rk=>$ak) if ($access_policy[$rk]) $access_policy[$ak]=$access_policy[$rk];
- $posix_av=is_callable("posix_setuid");
- $pcntl_av=is_callable("pcntl_fork");
- $gz_av=is_callable("gzencode");
- if (count($themes)==0) techo("WARN: No theme loaded, server generated content is disabled", NW_EL_WARNING);
-
- if ($posix_av) foreach ($conf as $vconf) {
- if ($u=$vconf["user"][0]) $sysusr[$u]=@posix_getpwnam($u);
- if ($g=$vconf["group"][0]) $sysgrp[$g]=@posix_getgrnam($g);
-
- }
- if ((!$conf["global"]["singleprocessmode"][0]) && (!$posix_av || !$pcntl_av || ($conf["global"]["servermode"][0]=="inetd"))) {
- techo("WARN: forcing single process mode", NW_EL_WARNING);
- $conf["global"]["singleprocessmode"][0]=true;
- }
- if ($conf["global"]["servermode"][0]=="inetd") {
-
- unset($conf["global"]["logtoconsole"]);
- unset($conf["global"]["pidfile"]);
- }
- if ($conf["global"]["singleprocessmode"][0]) {
-
- $conf["global"]["loggerprocess"]=0;
- if ($conf["global"]["keepalive"][0]) techo("WARN: KeepAlive should be set to 0 in single process mode", NW_EL_WARNING);
- }
- if ($pcntl_av) {
- pcntl_signal(SIGTERM, "nanoweb_shutdown");
- pcntl_signal(SIGHUP, "nanoweb_reload");
- }
- $mime=array();
-
- if (!@is_readable($conf["global"]["mimetypes"][0])) {
- techo("WARN: unable to read mime types file (".$conf["global"]["mimetypes"][0]."), using internals", NW_EL_WARNING);
- $mime=array( "html" => "text/html",
- "xml" => "text/xml",
- "gif" => "image/gif",
- "jpeg" => "image/jpeg",
- "png" => "image/png",
- "tgz" => "application/gtar");
- } else if ($mimetypes=@file($conf["global"]["mimetypes"][0])) {
-
- foreach ($mimetypes as $s) if (trim($s) && ($s{0}!="#")) if (ereg("([a-zA-Z0-9/.-]+)[ \t]+([a-zA-Z0-9 -]+)", $s, $res)) if ($exts=explode(" ", trim($res[2]))) foreach ($exts as $ext) if (trim($res[1]) && trim($ext)) $mime[$ext]=trim($res[1]);
- unset($mimetypes);
- }
- if ($at=$conf["global"]["addtype"]) foreach ($at as $adt) {
- $mt=strtok(trim($adt), " ");
- while ($s=strtok(" ")) $mime[ltrim($s, ".")]=$mt;
- }
- $conf["_complete"]=true;
- $banned_ips=array();
- if (is_array($conf["global"]["blockipaddr"])) foreach ($conf["global"]["blockipaddr"] as $ip) nw_block_ip_address($ip, "PERM", "config.BlockIPAddr");
- return(true);
- }
- function nanoweb_shutdown($sig_no=SIGTERM) {
- global $lsocks, $pidfile, $loggers_sck, $conf, $pmode;
-
- if ($pmode=="master") {
-
- modules_init("shutdown");
-
- if ($lsocks) foreach ($lsocks as $sock) socket_close($sock);
- if ($nb_loggers=$conf["global"]["loggerprocess"][0]) {
-
- techo("halting loggers");
-
- for ($a=0;$a<$nb_loggers;$a++) {
- $pkt="TERM";
-
- socket_write($loggers_sck, $pkt);
- usleep(100000);
-
- }
- sleep(1);
-
- }
- if ($pidfile) unlink($pidfile);
- techo("daemon stopped\n");
- }
- exit(0);
- }
- function nanoweb_reload($sig_no=SIGHUP) {
- global $mypid, $conffile, $conf, $loggers_sck, $logger_pids, $killed_loggers, $access_cache, $rp_cache;
- if (!$mypid) {
-
- techo("received SIGHUP, reloading configuration ...");
-
- clearstatcache();
- unset($access_cache);
- unset($rp_cache);
- if (nanoweb_init($conffile)) {
- if ($nb_loggers=$conf["global"]["loggerprocess"][0]) {
-
- techo("restarting loggers");
-
- foreach ($logger_pids as $lid) {
- $pkt="TERM";
-
- socket_write($loggers_sck, $pkt);
- usleep(100000);
- $killed_loggers[] = $lid;
- }
- sleep(1);
-
- }
-
- techo("configuration reloaded from ".$conffile);
-
- } else {
- techo("configuration was not reloaded", NW_EL_WARNING);
- }
- }
- }
- function read_request(&$sck_connected, &$dp, &$pn, $maxlen=0) {
-
- global $conf;
- static $rr_buffer;
-
- $wstart=time();
-
- if ($rr_buffer!=="") {
-
- $buf=$rr_buffer;
- $tnreq=true;
- }
-
- while (!$rq_finished && $sck_connected) {
-
- if (!$tnreq) {
-
- $fdset=$GLOBALS["pfdset"];
- if ($conf["global"]["servermode"][0]=="inetd") {
- // Inetd
- if (feof($GLOBALS["inetd_in"])) {
-
- $tmp=false;
- $sck_connected=false;
- } else $tmp=fgetc($GLOBALS["inetd_in"]);
- } else {
-
- if ($ns=socket_select($fdset, $write=NULL, $fdset, SCK_READ_SELECT_TIMEOUT)) $tmp=@socket_read($GLOBALS["msgsock"], SCK_READ_PACKET_SIZE); else $tmp=false;
- }
- }
- if ($tmp || $tmp==="0" || $tnreq) {
-
- $tnreq=false;
- $wstart=time();
- $buf.=$tmp;
- $pn=0;
- if (!$maxlen) {
-
- if (!$rnloop) {
-
- $buf=ltrim($buf);
- $rnloop=true;
- }
- if (($dp=strpos($buf, "\r\n\r\n"))!==false) $pn=4;
- else if (($dp=strpos($buf, "\n\n"))!==false) $pn=2;
- if ($pn) $rq_finished=true;
- } else {
- if (strlen($buf)>=$maxlen) $rq_finished=true;
- }
- } else if (($ns) || ((!$ns) && ((time()-$wstart)>=$conf["global"]["requesttimeout"][0]))) $sck_connected=false;
- }
-
- if (!$maxlen) {
- $tbuf=substr($buf, 0, $dp+$pn);
- $rr_buffer=substr($buf, $dp+$pn);
- $buf=$tbuf;
-
- } else {
- $tbuf=substr($buf, 0, $maxlen);
- $rr_buffer=substr($buf, $maxlen);
- $buf=$tbuf;
- }
-
- return($buf);
- }
- function send_response($response, &$sck_connected) {
- global $msgsock;
-
- $resp_len=strlen($response);
- while($sent_len<$resp_len && $sck_connected) {
- if ($GLOBALS["conf"]["global"]["servermode"][0]=="inetd") {
- // Inetd
-
- echo $response;
- $sent_len=strlen($response);
- } else {
- $fdset=$GLOBALS["pfdset"];
-
- if (($sent_len+SCK_WRITE_PACKET_SIZE)>$resp_len) $size=$resp_len-$sent_len; else $size=SCK_WRITE_PACKET_SIZE;
- if (($ret=@socket_write($msgsock, substr($response, $sent_len, $size), $size))>0) $sent_len+=$ret;
- if ($ret===false) {
-
- if (socket_last_error($msgsock)==SOCKET_EWOULDBLOCK) {
-
- socket_clear_error($msgsock);
- if (!socket_select($read=NULL, $fdset, $except=NULL, SCK_MAX_STALL_TIME)) $sck_connected=false;
- } else {
- $sck_connected=false;
-
- }
- }
- }
- }
- return($sent_len);
- }
- function int_sendtomaster($msg_type, $args=false) {
- if ((!$GLOBALS["conf"]["global"]["singleprocessmode"][0]) && ($GLOBALS["pmode"]!="master")) {
-
- $msg=$msg_type;
- if ($args!==false) $msg.=serialize($args);
-
- $ret=socket_write($GLOBALS["master_sck"], $msg);
- if ($ret!=strlen($msg)) {
- techo("WARN: master process is not responding", NW_EL_WARNING);
-
- }
- }
- }
- function _server_report_state($s, $remote_host="") {
- $tmp=array($GLOBALS["mypid"], $s);
- if ($remote_host) $tmp[]=$remote_host;
- int_sendtomaster(NM_SERVER_STATE, $tmp);
- }
- function nw_block_ip_address($ip_addr, $type, $source, $expires=0) {
- global $conf, $pmode, $banned_ips;
- if ((($conf["global"]["singleprocessmode"][0]) || ($pmode=="master")) && (!$banned_ips[$ip_addr])) {
-
- $banned_ips[$ip_addr]=array("type" => $type, "source" => $source, "expires" => $expires);
- techo($source." : blocked IP address ".$ip_addr." (".strtolower($type).")", NW_EL_BLOCKING);
- } else {
- int_sendtomaster(NM_BLOCK_IP, array($ip_addr, $type, $source, $expires));
-
- }
- }
- function nw_unblock_ip_address($ip_addr, $msg=false) {
- global $conf, $pmode, $banned_ips;
- if ((($conf["global"]["singleprocessmode"][0]) || ($pmode=="master")) && ($banned_ips[$ip_addr])) {
-
- $source=strtok($banned_ips[$ip_addr]["source"], ".");
- $rejs=$banned_ips[$ip_addr]["rejects"];
-
- unset($banned_ips[$ip_addr]);
- techo($source." : unblocked IP address ".$ip_addr." (".(int)$rejs." rejs".($msg===false?"":(", ".$msg)).")", NW_EL_BLOCKING);
- } else {
- int_sendtomaster(NM_UNBLOCK_IP, $ip_addr);
-
- }
- }
- function logger_run($logger_id) {
- global $conf, $children_logsck, $modules, $plgset, $pmode;
- $pmode="logger";
- pcntl_signal(SIGTERM, SIG_DFL);
- pcntl_signal(SIGHUP, SIG_IGN);
- $mypid=posix_getpid();
- $lids=log_ids();
- posix_setgid($lids["gid"]);
- posix_setuid($lids["uid"]);
- techo("logger process #".$logger_id." is running (pid=".$mypid.")");
- while (!$logger_exit) {
-
- $r=socket_read($children_logsck, INT_MSGSIZE);
- switch($r) {
- case "TERM":
- $logger_exit=true;
- break;
- default:
- $l=unserialize($r);
- // Reverse DNS query if the server hasn't done it before
-
- if (($conf["global"]["hostnamelookups"][0]) && ($conf["global"]["hostnamelookupsby"][0]=="logger") && ($rhost=nw_gethostbyaddr($l[2]))) $l[1]=$rhost;
- // And call the logging modules
-
- if ($nb_log_mods=count($modules["log"])) for ($a=0;$a<$nb_log_mods;$a++) $modules["log"][$a]->log_hit($l[0], $l[1], $l[2], $l[3], $l[4], $l[5], $l[6], $l[7], $l[8]);
- break;
-
- }
-
- }
- techo("logger process #".$logger_id." stopped");
- exit(0);
- }
- function spawn_loggers($nb_loggers) {
-
- global $logger_pids;
- static $logger_id;
- for ($a=0;$a<$nb_loggers;++$a) {
- $pid=pcntl_fork();
- ++$logger_id;
- if ($pid===0) {
-
- logger_run($logger_id);
- } else {
-
- $logger_pids[$pid]=$logger_id;
- if ($nb_loggers>1) usleep(100000);
- }
-
- }
- }
- // Begin
- set_time_limit(0);
- $pmode="master";
- techo("aEGiS nanoweb/".VERSION." (C) 2002-2005 by sIX / aEGiS");
- $stats_start=time();
- if (version_compare(phpversion(), REQUIRED_PHP_VERSION)<0) errexit("nanoweb needs PHP >= ".REQUIRED_PHP_VERSION." (you are using ".phpversion().")");
- if (version_compare(phpversion(), "4.3.0")>=0) $sckv3=true;
- $os=((strpos(strtolower(PHP_OS), "win")===0) || (strpos(strtolower(PHP_OS), "cygwin")!==false))?"win32":"unix";
- switch ($os) {
- case "win32":
- define("NW_BSAFE_READ_OPEN", "rb");
- define("NW_BSAFE_WRITE_OPEN", "wb");
- define("NW_BSAFE_APP_OPEN", "ab");
- if (!defined("SOCKET_EWOULDBLOCK")) define("SOCKET_EWOULDBLOCK", 10035);
- break;
- default:
- define("NW_BSAFE_READ_OPEN", "r");
- define("NW_BSAFE_WRITE_OPEN", "w");
- define("NW_BSAFE_APP_OPEN", "a");
- if (!defined("SOCKET_EWOULDBLOCK")) define("SOCKET_EWOULDBLOCK", 11);
- break;
- }
- foreach ($TEST_FUNCS as $f_name=>$f_mandatory) if (!is_callable($f_name)) {
- if ($f_mandatory) errexit("function '".$f_name."' not available, aborting");
- else techo("WARN: function '".$f_name."' not available", NW_EL_WARNING);
- }
- // Parse command line
- if ($_SERVER["argc"]>1) for($a=1;$a<$_SERVER["argc"];$a++) {
- if (($a==1) && (substr($_SERVER["argv"][$a], 0, 1)!="-")) {
- $cmdline_cf=$_SERVER["argv"][1];
-
- } else {
- $ca=explode("=", $_SERVER["argv"][$a]);
- $ck=array_shift($ca);
- $cv=implode("=", $ca);
- switch($ck) {
- case "-?":
- case "-h":
- case "--help":
- die($cmdline_help);
- break;
- case "-v":
- case "--version":
- die(VERSION."\n");
- break;
-
- case "-c":
- case "--config":
- $cmdline_cf=$cv;
- break;
- case "-o":
- case "--set-option":
- $cmdline_conf_overrides[]=$cv;
- break;
- case "-a":
- case "--add-option":
- $cmdline_conf_adds[]=$cv;
- break;
- case "-d":
- case "--start-daemon":
- $start_daemon=true;
- break;
-
- case "-q":
- case "--quiet":
- $quiet=true;
- break;
- case "--debug":
- $nw_debug=true;
- case "--verbose":
- break;
-
- case "--config-test":
- case "-t":
- $config_test=true;
- break;
-
- default:
- errexit("unknown argument : ".$_SERVER["argv"][$a].", try --help");
- break;
- }
-
- }
-
- }
- if ($cmdline_cf) $conffile=$cmdline_cf; else $conffile=DEFAULT_CONFIG_FILE;
- if (!is_readable($conffile)) errexit("unable to read configuration (".$conffile."), aborting");
- unset($cmdline_help);
- nanoweb_init($conffile);
- if ($config_test) {
-
- techo("configuration test successful");
- exit(0);
- }
- if ($conf["global"]["servermode"][0]!="inetd") {
- // Create socket(s) and start listening
-
- if ($sckv3) {
-
- $setsockopt="socket_set_option";
- $getsockopt="socket_get_option";
- } else {
-
- $setsockopt="socket_setopt";
- $getsockopt="socket_getopt";
- }
-
- foreach ($conf["global"]["listenport"] as $lport) {
-
- $lport=(int)$lport;
-
- if (($sock = @socket_create(AF_INET, SOCK_STREAM, 0))<0) errexit("socket create failed : ".socket_strerror(socket_last_error()));
- if (is_callable($setsockopt) && is_callable($getsockopt)) {
-
- $setsockopt($sock, SOL_SOCKET, SO_REUSEADDR, 1);
- $sbuf=$getsockopt($sock, SOL_SOCKET, SO_SNDBUF);
- $rbuf=$getsockopt($sock, SOL_SOCKET, SO_RCVBUF);
- if ($sbuf<(SCK_WRITE_PACKET_SIZE*32)) $setsockopt($sock, SOL_SOCKET, SO_SNDBUF, SCK_WRITE_PACKET_SIZE*32);
- if ($rbuf<(SCK_READ_PACKET_SIZE*32)) $setsockopt($sock, SOL_SOCKET, SO_RCVBUF, SCK_READ_PACKET_SIZE*32);
- }
-
- if (!@socket_bind($sock, $conf["global"]["listeninterface"][0], $lport)) errexit("socket bind failed on port ".$lport." : ".socket_strerror(socket_last_error($sock)));
- if (!@socket_listen($sock, $conf["global"]["listenqueue"][0])) errexit("socket listen failed on port ".$lport." : ".socket_strerror(socket_last_error($sock)));
- socket_set_nonblock($sock);
- $lsocks[$lport]=$sock;
- $lports[$sock]=$lport;
- }
- }
- if ($pcntl_av) {
- $sck_pair=array();
- socket_create_pair(AF_UNIX, SOCK_DGRAM, 0, $sck_pair);
- $children_sck=&$sck_pair[0];
- $master_sck=&$sck_pair[1];
- socket_set_nonblock($children_sck);
- socket_set_nonblock($master_sck);
- }
- $plnset=array($children_sck);
- foreach ($lsocks as $sck) $plnset[]=$sck;
- if ($conf["global"]["servermode"][0]!="inetd") {
- techo("listening on port".(count($lports)>1?"s":"")." ".implode(", ", $lports));
- $stdfd = fopen("php://stdin", "r");
- fclose($stdfd);
- $stdfd = fopen(($os == "unix") ? "/dev/null" : "NUL", "r");
- } else {
- $inetd_in=fopen("php://stdin", NW_BSAFE_READ_OPEN);
- set_file_buffer($inetd_in, 0);
- techo("running in inetd mode");
- }
- $def_cnx=($conf["global"]["servermode"][0]=="inetd");
- if ($start_daemon) {
- if (!$posix_av || !$pcntl_av) errexit("posix and pcntl PHP extensions are needed for --start-daemon");
- $npid = pcntl_fork();
- if ($npid == -1) {
-
- errexit("unable to pcntl_fork()");
- } else if ($npid) {
- exit(0);
- }
- posix_setsid();
- usleep(100000);
- $npid = pcntl_fork();
- if ($npid == -1) {
-
- errexit("unable to pcntl_fork()");
- } else if ($npid) {
- techo("running in background");
- exit(0);
- }
- }
- if ($nb_loggers=$conf["global"]["loggerprocess"][0]) {
- // Prepare and spawn logger processes if specified
-
- techo("spawning loggers");
- $sck_pair=array();
- socket_create_pair(AF_UNIX, SOCK_DGRAM, 0, $sck_pair);
- $children_logsck=&$sck_pair[0];
- $loggers_sck=&$sck_pair[1];
-
- socket_set_nonblock($loggers_sck);
-
- spawn_loggers($nb_loggers);
- } else {
- // Be sure not to ask anything to loggers
- $conf["global"]["hostnamelookupsby"][0]="server";
- }
- if ($posix_av && $conf["global"]["pidfile"][0]) {
-
- $pidfile=$conf["global"]["pidfile"][0];
-
- if ($f=fopen($pidfile, "w")) {
-
- fputs($f, (string)posix_getpid()."\n");
- fclose($f);
- } else {
- techo("WARN: unable to open pid file '".$pidfile."'", NW_EL_WARNING);
- unset($pidfile);
-
- }
- }
- if (empty($nw_debug)) error_reporting(E_PARSE | E_ERROR);
- if ($conf["global"]["servermode"][0]!="inetd") techo("ready and accepting connections");
- while (true) {
- $cnx=$def_cnx;
-
- while (!$cnx) {
- declare (ticks = 1) {
-
- // Allow to catch signals here
-
- $lnset=$plnset;
- }
-
- $ns=socket_select($lnset, $write=NULL, $except=NULL, 1);
-
- if ($ns) foreach ($lnset as $lnact) {
-
- if ($lnact==$children_sck) {
-
- while ($msg=socket_read($children_sck, INT_MSGSIZE)) {
- // Message from a child process
-
- $mtype=substr($msg, 0, 5);
- if (strlen($msg)>5) $mcontent=unserialize(substr($msg, 5));
- switch ($mtype) {
- case NM_HIT:
-
- // content : 0 => pid, 1 => request status, 2 => length, 3 => vhost
-
- if (is_array($mcontent)) {
- ++$stats_resperr[$mcontent[1]];
- ++$stats_vhosts[$conf[$mcontent[3]]["servername"][0]];
- ++$stats_hits;
- $stats_xfer+=(float)$mcontent[2];
-
- if ($scoreboard[$spid=$mcontent[0]]) {
-
- $scoreboard[$spid][NW_SB_STATUS]="(waiting for request)";
- }
- }
- break;
- case NM_RESTART_LOGGERS:
- techo("respawning loggers");
- spawn_loggers($conf["global"]["loggerprocess"][0]);
-
- break;
- case NM_RELOAD_THEME:
- // content : theme id
-
- clearstatcache();
- if ((is_array($themes[$mcontent])) && ($themes[$mcontent]["_mtime"]!=filemtime($fname=$themes[$mcontent]["_fname"]))) {
-
- $tmp_thm=load_theme($fname, true, true);
- $themes[$mcontent]=$tmp_thm;
- $themes[$fname]=$tmp_thm;
- $themes[$tmp_thm["_fname"]]=$tmp_thm;
- }
- break;
- case NM_SERVER_STATE:
- // content : 0 => pid, 1 => status text, 2 => remote host
-
- if ($scoreboard[$spid=$mcontent[0]]) {
-
- $scoreboard[$spid][NW_SB_STATUS]=$mcontent[1];
- if ($mcontent[2]) $scoreboard[$spid][NW_SB_PEERHOST]=$mcontent[2];
- }
-
- break;
- case NM_BLOCK_IP:
- // content : 0 => ip address, 1 => type (PERM|TEMP), 2 => source, 3 => expiration
- if (is_array($mcontent)) nw_block_ip_address($mcontent[0], $mcontent[1], $mcontent[2], $mcontent[3]);
- break;
-
- case NM_UNBLOCK_IP:
- // content : ip address
-
- if ($mcontent) nw_unblock_ip_address($mcontent);
-
- break;
-
- }
- }
- } else {
- $sock=$lnact;
- $lport=$lports[$sock];
- if ((($active_servers<$conf["global"]["maxservers"][0]) || (!$conf["global"]["maxservers"][0])) && (is_resource($msgsock=@socket_accept($sock)))) {
-
- // We do have a connection
-
- $remote_ip=$remote_port=0;
- socket_getpeername($msgsock, $remote_ip, $remote_port);
-
- if (is_array($banned_ips[$remote_ip])) {
- // Disconnect if IP address is banned
- techo("rejected connection #".(++$banned_ips[$remote_ip]["rejects"])." from blocked IP address ".$remote_ip, NW_EL_BLOCKING);
- socket_close($msgsock);
-
- ++$stats_rej;
-
- } else if ($remote_ip) {
-
- // Or handle the new connection
-
- $cnx=true;
- ++$stats_cnx;
- } else {
- // Cannot obtain peer IP address, something is wrong (but not worth throwing a notice)
-
- socket_close($msgsock);
-
- }
-
- }
-
- }
-
- }
- if (!$conf["global"]["singleprocessmode"][0]) while (($deadpid=pcntl_waitpid(-1, $cstat, WNOHANG)) && ($deadpid!=-1)) {
- // Dead child
- if (($dead_logger=$logger_pids[$deadpid]) && ($conf["global"]["loggerprocess"][0])) {
- // Dead logger (this is abnormal, we have to restart one)
- if (in_array($dead_logger, $killed_loggers)) {
- unset($killed_loggers[array_search($dead_logger, $killed_loggers)]);
-
- } else {
-
- techo("logger process #".$dead_logger." died (pid=".$deadpid."), respawning", NW_EL_WARNING);
- }
-
- unset($logger_pids[$deadpid]);
-
- spawn_loggers(1);
-
- } else {
- // Dead child server, clear servers table
- unset($scoreboard[$deadpid]);
- --$active_servers;
-
- }
-
- }
- $ct=time();
- foreach ($banned_ips as $ip_addr=>$bip) if (($bip["type"]=="TEMP") && ($bip["expires"]<=$ct)) nw_unblock_ip_address($ip_addr, "expired");
-
- }
-
- if ($conf["global"]["singleprocessmode"][0]) {
-
- $pid=0;
- // Invalidate access and rp caches every SPM_CACHES_LIFETIME connections
- if (($stats_cnx%SPM_CACHES_LIFETIME)==0) {
-
- clearstatcache();
- unset($access_cache);
- unset($rp_cache);
- }
- } else {
-
- $pid=pcntl_fork();
- if ($pid===0) $pmode="server";
- }
- if ($pid===0) {
-
- if ($posix_av) $mypid=posix_getpid();
-
- if (!$conf["global"]["singleprocessmode"][0]) {
-
- foreach ($lsocks as $sock) socket_close($sock);
-
- set_time_limit($conf["global"]["childlifetime"][0]);
- }
-
- if ($conf["global"]["servermode"][0]!="inetd") {
-
- socket_set_nonblock($msgsock);
- $pfdset=array($msgsock);
- if (($conf["global"]["hostnamelookups"][0]) && ($conf["global"]["hostnamelookupsby"][0]!="logger") && ($rhost=nw_gethostbyaddr($remote_ip))) {
-
- $remote_host=$rhost;
- _server_report_state("(connected)", $remote_host);
- } else {
-
- $remote_host=$remote_ip;
- }
- } else {
- $remote_ip=getenv("INETD_REMOTE_IP");
- $remote_port=getenv("INETD_REMOTE_PORT");
-
- }
- $rq_count=0;
-
- while ($cnx) {
-
- $sck_connected=true;
- $http_continue=false;
- $http_rq_block=$buf=read_request($sck_connected, $dp, $pn);
- $pri_redir=$http_uri=$out_headers="";
- $pri_err=$pri_redir_code=$rq_err=0;
- $add_nsv=$htreq_headers=$out_add_headers=array();
- if ($sck_connected) {
- if (strlen($buf)!=$dp+4) $add_req=substr($buf, $dp+4); else $add_req="";
- $tmp_arr=explode("\n", substr($buf, 0, $dp));
- $l=false;
-
- foreach ($tmp_arr as $s) {
-
- $s=trim($s);
- if (!$l) {
- $http_action=strtok($s, " ");
- $http_resource=strtok(" ");
- $http_protocol=strtoupper(strtok("/"));
- $http_version=strtok("");
- $l=true;
- if ($http_protocol!="HTTP") {
- // Invalid protocol
- $pri_err=400;
- $add_errmsg="Unable to serve requested protocol.<br><br>";
-
- }
- } else {
- if (strpos($s, ":")===false) {
- // Invalid request header
- $pri_err=400;
- $add_errmsg="Invalid request header received.<br><br>";
-
- } else {
-
- $hd_key=strtoupper(strtok($s, ":"));
- $hd_val=trim(strtok(""));
- if (isset($htreq_headers[$hd_key])) {
- $pri_err=400;
- $add_errmsg="Duplicate request header '{$hd_key}'<br><br>";
- } else {
-
- $htreq_headers[$hd_key]=$hd_val;
- }
- }
- }
-
- }
- // Decode Host header
-
- $host=strtok(trim(strtolower($htreq_headers["HOST"])), ":");
- $vhost=nw_host_to_vhost($host, $lport);
- if ($auth_hdr=$htreq_headers["AUTHORIZATION"]) {
- // Decode HTTP Authentication header
- $dtmp=explode(" ", $auth_hdr);
- $auth_type=$dtmp[0];
- $auth_lp=explode(":", base64_decode($dtmp[1]));
- $auth_user=$auth_lp[0];
- $auth_pass=$auth_lp[1];
-
- } else $auth_type=$auth_user=$auth_pass="";
- // Decode Keep-Alive header
-
- $keepalive=(strtolower(trim($htreq_headers["CONNECTION"]))=="keep-alive" && (int)$conf["global"]["keepalive"][0]>1);
- if ($keepalive && (++$rq_count>=(int)$conf["global"]["keepalive"][0])) $keepalive=false;
- $cnx=$keepalive;
-
- // Set Uid and Gid
- $cfgid=$conf[$vhost]["group"][0];
- $cfuid=$conf[$vhost]["user"][0];
- if ($posix_av) {
-
- $ugtok=$sysusr[$cfuid]["uid"].$sysgrp[$cfgid]["gid"];
-
- if ($uid_set) {
- if ($uid_set!=$ugtok) {
- // Keep-alive request for another user/group vhost, this is bad
-
- $pri_err=400;
-
- }
-
- } else {
-
- if ($setgid=$sysgrp[$cfgid]["gid"]) posix_setgid($setgid);
- if ($setuid=$sysusr[$cfuid]["uid"]) posix_setuid($setuid);
- $uid_set=$ugtok;
-
- }
-
- }
-
- $docroot=$conf[$vhost]["documentroot"][0];
- $docroot_prefix="";
- if ($exp_hdr=$htreq_headers["EXPECT"]) {
- // Enforce HTTP Expect header
- if (trim(strtolower($exp_hdr))=="100-continue") {
-
- $http_continue=true;
- } else {
- $pri_err=417;
-
- }
-
- }
-
- if ($p1=$http_resource) {
- $p1=explode("?", $p1);
- $real_uri=ltrim($http_uri=rawurldecode($p1[0]), "/");
- $http_uri=str_replace(chr(0), "", $http_uri);
- $query_string=$p1[1];
- $hu=$docroot.$real_uri;
- // Load access files if needed
-
- unset($access);
-
- if (is_dir($hu)) {
-
- $uridir=substr($http_uri, 1);
-
- } else if (is_dir($docroot.($uridn=dirname($http_uri)))) {
- $uridir=substr($uridn, 1);
-
- } else $uridir="";
- if (($accessdir=nw_realpath($docroot.$uridir)) && ($conf["global"]["accessfile"][0])) load_access_files($accessdir, $access);
- core_modules_hook("before_decode");
- foreach (access_query("_aliases") as $key=>$val) if (strpos(rtrim($http_uri, "/"), rtrim($key, "/"))===0) {
- // Alias
-
- $docroot=$val.((substr($val, -1)==DIRECTORY_SEPARATOR)?"":DIRECTORY_SEPARATOR);
- $docroot_prefix=trim($key, "/")."/";
- $http_uri=str_replace($key, "", $http_uri);
- if ((is_dir($docroot.$http_uri)) && (substr($docroot.$http_uri, -1)!="/")) $pri_redir=nw_url_addslash($http_resource);
- break;
- }
- $http_uri=ltrim($http_uri, "/");
-
- if ($http_uri{0}=="~") {
-
- // User directory
-
- if (($udadd=$conf[$vhost]["userdir"][0]) && ($posix_av)) {
- $upos=strpos($http_uri, "/");
-
- $udname=substr($http_uri, 1, (($upos===false)?(strlen($http_uri)):($upos-1)));
- $udres=(($upos===false)?"":(substr($http_uri, $upos+1)));
-
- if ($udinf=@posix_getpwnam($udname)) {
- $tmpdr=$udinf["dir"].DIRECTORY_SEPARATOR.$udadd.DIRECTORY_SEPARATOR;
-
- if (is_dir($tmpdr)) {
- if ((is_dir($tmpdr.$udres)) && (substr($http_uri, -1)!="/")) {
-
- $pri_redir=nw_url_addslash($http_resource);
- } else {
-
- $docroot=$tmpdr;
- $docroot_prefix="~".$udname."/";
- $http_uri=$udres;
-
- }
-
- } else {
- // User exists but does not have a public html directory
-
- $pri_err=404;
-
- }
-
- } else {
- // User does not exists
-
- $pri_err=404;
-
- }
- }
-
- }
-
- if (is_dir($docroot.$http_uri) && !$pri_redir) {
-
- if ($http_uri && substr($http_uri, -1)!="/") {
- $pri_redir=nw_url_addslash($http_resource);
-
- } else if ($dilist=access_query("directoryindex", 0)) {
-
- $dis=explode(" ", $dilist);
- foreach ($dis as $diname) {
-
- switch ($diname{0}) {
-
- case DIRECTORY_SEPARATOR:
- if (@is_readable($diname)) {
- $docroot=dirname($diname).DIREECTORY_SEPARATOR;
- $http_uri=basename($diname);
- break;
-
- }
-
- break;
-
- default:
-
- if (@is_readable($docroot.$http_uri.$diname)) {
- $http_uri.=$diname;
- break;
- }
-
- }
-
- }
- }
- }
- $path_info="";
-
- if (access_query("allowpathinfo", 0) && !file_exists($docroot.$http_uri)) {
-
- // Try path_info
- $new_uri=$http_uri;
-
- while (!@is_file($docroot.$new_uri) && $new_uri) {
- $new_uri=substr($new_uri, 0, strrpos($new_uri, "/"));
- if (!@is_file($docroot.$new_uri) && $pie_arr=access_query("pathinfotryext")) foreach ($pie_arr as $pie_ext) if (@is_file($docroot.$new_uri.".".$pie_ext)) {
- $new_uri.=".".$pie_ext;
- break;
-
- }
- }
- if ($new_uri) {
- // Path_info found
- $path_info=substr($http_uri, strlen($new_uri));
- $http_uri=$new_uri;
-
- }
-
- }
-
- $rq_file=pathinfo($http_uri);
- }
- $hbn=basename($http_uri);
- unset($bad_rq);
-
- // File access security tests
-
- if (nw_realpath($docroot.$http_uri) && (strpos(nw_realpath($docroot.$http_uri), nw_realpath($docroot))===false)) {
-
- $bad_rq=NW_BAD_OUTSIDE_DOCROOT;
- }
-
- if (($conf[$vhost]["ignoredotfiles"][0]) && ($hbn{0}==".") && ($hbn!="..") && ($hbn!=".")) {
- $bad_rq=NW_BAD_DOT_FILE;
-
- }
- if (($os == "win32") && in_array(strtolower(strtok($hbn, ".")), $win_devices)) {
-
- $bad_rq=NW_BAD_WIN_DEVICE;
- }
-
- if (($bad_rq==NW_BAD_OUTSIDE_DOCROOT) && ($als_arr=$conf[$vhost]["allowsymlinkto"])) {
-
- // Test for outside-docroot access exemptions (AllowSymlinkTo)
-
- $tdir=$http_uri;
- while ($tdir) {
-
- if ((is_link($docroot.$tdir)) && (strpos(nw_realpath(dirname($docroot.$tdir)), nw_realpath($docroot))===0)) foreach ($als_arr as $als) if (strpos(nw_realpath($docroot.$http_uri), nw_realpath($als))===0) {
- unset($bad_rq);
- break 2;
- }
-
- $tdir=substr($tdir, 0, strrpos($tdir, "/"));
-
- }
- }
- if ($bad_rq) switch ($bad_rq) {
- case NW_BAD_OUTSIDE_DOCROOT:
- techo("NOTICE: discarded request outside of document root (".$docroot.$http_uri.")");
- $http_uri="";
- $pri_err=404;
- break;
- case NW_BAD_DOT_FILE:
- techo("NOTICE: discarded request for dot file (".$docroot.$http_uri.")");
- $http_uri="";
- $pri_err=404;
- break;
- case NW_BAD_WIN_DEVICE:
- techo("NOTICE: discarded request for windows device file (".$docroot.$http_uri.")");
- $http_uri="";
- $pri_err=404;
- break;
-
- }
- $sst=$http_action." http://".$htreq_headers["HOST"]."/".$real_uri.($query_string?("?".$query_string):"");
- _server_report_state($sst);
- if ($hu!=($docroot.$http_uri)) {
-
- // Reload access files if needed
-
- $hu=$docroot.$http_uri;
- unset($access);
-
- if (is_dir($hu)) {
-
- $uridir=$http_uri;
- } else if (is_dir($docroot.($uridn=dirname($http_uri)))) {
- $uridir=$uridn;
-
- } else $uridir="";
- if (($accessdir=nw_realpath($docroot.$uridir)) && ($conf["global"]["accessfile"][0])) {
-
- load_access_files($accessdir, $access);
- }
- }
-
- $out_contenttype=$default_ct=access_query("defaultcontenttype", 0);
-
- // AuthLocation handler
-
- $bypass_auth = false;
-
- if ($authls=access_query("authlocation")) {
-
- $bypass_auth = true;
-
- foreach ($authls as $authl) if (strpos("/".$real_uri, $authl) === 0) {
- $bypass_auth = false;
- break;
- }
-
- }
-
- // Auth handler
-
- $logged_user="";
-
- if (($rauths=access_query("authrequire")) && (!$bypass_auth)) {
-
- foreach ($rauths as $rauth) {
- if ($spos=strpos($rauth, " ")) {
-
- $authtype=strtolower(strtok($rauth, " "));
- $authargs=trim(strtok(""));
- } else {
- $authtype=strtolower($rauth);
- $authargs="";
- }
-
- $authmodn="auth_".strtolower($authtype);
- if (is_object($modules[$authmodn][0])) {
-
- if ($modules[$authmodn][0]->auth($auth_user, $auth_pass, $authargs)) {
- $logged_user=$auth_user;
- break;
-
- }
- } else {
- techo("WARN: authentication module not found for type '".$authtype."'", NW_EL_WARNING);
-
- }
- }
-
- if ($logged_user==="") {
-
- $logged_user=" ";
- $pri_err=401;
- $out_add_headers["WWW-Authenticate"]="Basic realm=\"".access_query("authrealm", 0)."\"";
- if ($emsg=access_query("authmessage", 0)) $add_errmsg.=$emsg."<br><br>";
- }
-
- }
-
- // Test for maximum URI length
- if (($conf[$vhost]["maxrequesturilength"][0]) && (strlen($http_resource)>$conf[$vhost]["maxrequesturilength"][0])) {
- $pri_err=414;
-
- }
-
- if ($htreq_headers["CONTENT-LENGTH"]) {
- // Read request content if there is one (POST requests)
-
- if (($maxblen=$conf[$vhost]["maxrequestbodylength"][0]) && ((int)$htreq_headers["CONTENT-LENGTH"]>$maxblen)) {
- // Request content is too large
- $pri_err=413;
-
- } else {
-
- if ($http_continue && !$pri_err) send_response(HTTP_VERSION." ".$HTTP_HEADERS[100]."\r\n\r\n", $sck_connected);
- $buf=$add_req;
- if (strlen($buf)<$htreq_headers["CONTENT-LENGTH"]) $buf.=read_request($sck_connected, $dp, $pn, $htreq_headers["CONTENT-LENGTH"]-strlen($buf));
- $htreq_content=substr($buf, 0, $htreq_headers["CONTENT-LENGTH"]);
- }
-
- }
-
- core_modules_hook("after_decode");
- if ($sck_connected) {
- switch ($http_action) {
- case "POST":
- if ((!access_query("_parseext", "_".strtolower($rq_file["extension"]))) && (is_file($docroot.$http_uri)) && (!$pri_parser)) {
-
- // Disallow POST on static content
-
- $pri_err=405;
- $out_add_headers["Allow"]=nw_allow_list($rq_file["extension"]);
- }
-
- case "GET":
- case "HEAD":
- if ($pri_err) {
- // Internal setting of http error
- $rq_err=$pri_err;
-
- } else if ($pri_redir) {
- // Internal redirection
- if ($rq_err<300) {
-
- $rq_err=$pri_redir_code
- or $rq_err=302;
- }
- $out_add_headers["Location"]=$pri_redir;
- if (version_compare($http_version, "1.0")<=0) $out_add_headers["URI"]=$pri_redir;
- } else if (is_object($umod=&$modules["url:/".$http_uri])) {
- // Module URL Hook
- if ($umod->modtype=="url2") {
- $lf=$umod;
- $lf->parser_open("", $real_uri, $rq_err, $out_add_headers, $out_contenttype);
-
- } else {
-
- $lf =& new static_response($umod->url($rq_err, $out_contenttype, $out_add_headers));
- }
-
- } else if (is_dir($docroot.$http_uri)) {
- // Directory without index
- $rq_err=404;
- core_modules_hook("directory_handler");
- } else if (!is_file($docroot.$http_uri)) {
-
- // 404 Not Found
- $rq_err=404;
- } else if (!is_readable($docroot.$http_uri)) {
-
- // 403 Forbidden
-
- $rq_err=403;
- } else {
- // 200 OK
- $rq_err=200;
- if ($pp=access_query("forcehandler", 0)) $pri_parser=$pp;
- $lf=loadfile($docroot.$http_uri, $rq_file["extension"], $rq_err, $out_add_headers, $pri_parser);
- /* libphpHACK */
- #<off># if (isset($__nw_libphp_script)) { include($__nw_libphp_script); exit; }
-
- if ($mimetype=$mime[strtolower($rq_file["extension"])]) {
-
- // Lookup mime type in internal table
-
- $out_contenttype=$mimetype;
-
- } else if (is_callable("mime_content_type") && (!access_query("disablemimemagic", 0)) && ($mimetype=mime_content_type($docroot.$http_uri))) {
- // Fallback to mime magic if available
- $out_contenttype=$mimetype;
- } else {
-
- // Or use default
- $out_contenttype=$default_ct;
- }
- }
- break;
- case "OPTIONS":
-
- $rq_err=200;
- $out_add_headers["Allow"]=nw_allow_list($rq_file["extension"]);
-
- break;
- default:
- if ($mmod=$modules["method:".$http_action]) {
- $rq_err=200;
- $lf=$mmod;
- $lf->parser_open("", $real_uri, $rq_err, $out_add_headers, $out_contenttype);
- } else if (!$http_action) {
- $rq_err=400;
-
- } else {
-
- $rq_err=501;
- }
- break;
- }
- unset($pri_parser);
- if ($rq_err!=200 && $rq_err!=416) {
- // Error messages
-
- if ($rq_err>=400) {
- if (($errordoc=trim(access_query("_errordocument", "_".$rq_err))) && (@is_readable($docroot.$errordoc))) {
- $add_nsv["REDIRECT_STATUS"]=$rq_err;
- $add_nsv["REDIRECT_URL"]="/".$GLOBALS["real_uri"];
- $http_uri=$errordoc;
- $errext=substr(strrchr($errordoc, "."), 1);
- $lf=loadfile($docroot.$errordoc, $errext, $rq_err, $out_add_headers);
- if ($mimetype=$mime[strtolower($errext)]) $out_contenttype=$mimetype; else $out_contenttype=$default_ct;
-
- } else {
-
- $out_contenttype="text/html";
- $lf =& new static_response(nw_error_page($rq_err));
-
- if ($errordoc) techo("WARN: unable to read error document : [".$rq_err."] ".$errordoc, NW_EL_WARNING);
- }
-
- $cnx=false;
-
- } else if ($rq_err>=301) {
- $lf=$null_response;
-
- }
-
- }
- if ($http_action=="HEAD") {
-
- $plen=$lf->content_length;
- $hlf=$lf;
- $lf=$null_response;
- $lf->content_length=$plen;
- }
- core_modules_hook("before_response");
- if (!$rq_err) $rq_err=500;
-
- $chunked=nw_use_chunked_encoding();
- if ($chunked==="CLOSE") $cnx=$keepalive=$chunked=false;
- // Send the response headers and content
- $sent_len=0;
- $first_chunk=true;
- while ((($buf = $lf->parser_get_output()) !== "") || $first_chunk) {
- if ($first_chunk) {
- $hbuf=build_response_headers()."\r\n";
-
- }
-
- if ($chunked) {
- $chunk_header=dechex(strlen($buf))."\r\n";
- $metasize=strlen($chunk_header)+2;
- $rbytes=send_response($hbuf.($buf!==""?$chunk_header.$buf."\r\n":""), $sck_connected);
- $sent_len+=($rbytes-$metasize);
- } else {
- $sent_len+=send_response($hbuf.$buf, $sck_connected);
-
- }
- if ($first_chunk) {
-
- $sent_len-=strlen($hbuf);
- $hbuf="";
- $first_chunk=false;
- }
-
- if ($lf->parser_eof() || !$sck_connected || ($buf === NULL)) break;
- }
- $lf->parser_close();
- if ($chunked) {
-
- $meta_len=0;
- send_response("0\r\n\r\n", $sck_connected);
- }
- if (!$sck_connected) $cnx=false;
- if (($sent_content_length=$sent_len-$meta_len)<0) $sent_content_length=0;
- if ($conf["global"]["singleprocessmode"][0]) {
-
- // Increment stats
-
- ++$stats_resperr[$rq_err];
- ++$stats_vhosts[$conf[$vhost]["servername"][0]];
- ++$stats_hits;
- $stats_xfer+=(float)$sent_len;
- } else {
-
- // Report hit to master
-
- int_sendtomaster(NM_HIT, array($mypid, $rq_err, $sent_len, $vhost));
- }
-
- if ($conf["global"]["loggerprocess"][0]) {
-
- // Send the logging infos to dedicated processes
-
- $log_arr=array($vhost, $remote_host, $remote_ip, $logged_user, trim($tmp_arr[0]), $rq_err, $sent_content_length, $htreq_headers["REFERER"], $htreq_headers["USER-AGENT"]);
- $logmsg=serialize($log_arr);
- $msglen=strlen($logmsg);
- if ($msglen>INT_MSGSIZE) {
- techo("WARN: internal communication error (packet too long)", NW_EL_WARNING);
-
- } else {
- $r=socket_write($loggers_sck, $logmsg);
- if ($r!=$msglen) techo("WARN: unable to communicate with logger process", NW_EL_WARNING);
-
- }
- } else {
- // Or do it ourselves
-
- if ($nb_loggers=count($modules["log"])) {
- for ($a=0;$a<$nb_loggers;$a++) $modules["log"][$a]->log_hit($vhost, $remote_host, $remote_ip, $logged_user, trim($tmp_arr[0]), $rq_err, $sent_content_length, $htreq_headers["REFERER"], $htreq_headers["USER-AGENT"]);
- }
- }
- $hlf=$lf=$null_response;
- }
-
- } else {
- $cnx=false;
-
- }
- }
-
- socket_shutdown($msgsock);
- socket_close($msgsock);
-
- if ((!$conf["global"]["singleprocessmode"][0]) || ($conf["global"]["servermode"][0]=="inetd")) exit(0);
-
- } else if ($pid==-1) {
- // Fork failed
-
- techo("WARN: unable to pcntl_fork()", NW_EL_WARNING);
- } else {
- // Fork successful
-
- $scoreboard[$pid][NW_SB_STATUS]="(connected)";
- $scoreboard[$pid][NW_SB_PEERHOST]=$remote_ip;
- $scoreboard[$pid][NW_SB_FORKTIME]=time();
- ++$active_servers;
-
- }
-
- }
- ?>