| [ PHPXref.com ] | [ Generated: Sun Jul 20 21:01:33 2008 ] | [ web-cp 0.5.7 ] |
| [ Index ] [ Variables ] [ Functions ] [ Classes ] [ Constants ] [ Statistics ] | ||
[Summary view] [Print] [Text view]
1 #!/usr/bin/php 2 <? /* 3 // File: webcp-httpd.php 4 // Purpose: web://cp HTTP Daemon 5 // Creation: 2003-01-25 6 // Author: Jonathan Haskins <jhaskins@killobyte.com> 7 */ 8 /********************************************* 9 * Main 10 *********************************************/ 11 error_reporting(E_ALL); 12 /* change to the script directory since php CLI doesn't do it automatically */ 13 chdir(dirname(__FILE__)); 14 /* include configuration file and functions */ 15 include ('webcp-httpd-functions.inc.phps'); 16 include ('../web/functions.inc.phps'); 17 include ('../web/config.inc.php'); 18 set_error_handler('error_handler'); 19 /* Make sure the php CLI/CGI has the needed modules */ 20 $i = 0; 21 unset($error); 22 if ((int)substr(preg_replace("/[^\d]*/", '', phpversion()), 0, 3) < 410) 23 $error[++$i] = "PHP Error: You must be running PHP version 4.1 or higher.\n"; 24 if (!extension_loaded('mysql')) 25 $error[++$i] = "PHP Error: The MySQL module is required (configure PHP '--with-mysql=/usr')\n"; 26 if (!extension_loaded('posix')) 27 $error[++$i] = "PHP Error: The POSIX module is required (configure PHP '--enable-posix')\n"; 28 if (!extension_loaded('pcre')) 29 $error[++$i] = "PHP Error: The Perl Compatible Regular Expressions module is required (configure PHP '--with-pcre-regex')\n"; 30 if (!extension_loaded('pcntl')) 31 $error[++$i] = "PHP Error: The Process Control module is required (configure PHP '--enable-pcntl')\n"; 32 if (!extension_loaded('sockets')) 33 $error[++$i] = "PHP Error: The Sockets module is required (configure PHP '--enable-sockets')\n"; 34 if ($cfg['httpd_mode'] != 'webcp') 35 $error[++$i] = "Configuration Error: The setting \$cfg['httpd_mode'] must be set to 'webcp'\n"; 36 if (isset($error)) { 37 webcp_log(2,0,'webcp-httpd',implode("\n", $error),0,1); 38 exit; 39 } 40 /* Run from root only */ 41 if (posix_getuid() != 0) { 42 webcp_log(1,0,'webcp-httpd',"This program must be started as root (uid 0).\n",0,1); 43 exit; 44 } 45 /* Check if we are run interactively or with the -d switch; keep on going or become a daemon */ 46 $args = trim(next($HTTP_SERVER_VARS["argv"])); 47 if ($args == '-d' OR $args == '--daemon') { 48 /* do not echo to terminal */ 49 $echo = 0; 50 } else { 51 webcp_log(3,0,'webcp-httpd',"web://cp ".$cfg['webcp']." httpd daemon usage: 52 webcp-httpd.php (run interactively) 53 webcp-httpd.php -i (run interactively) 54 webcp-httpd.php -d, --daemon (run as daemon) 55 webcp-httpd.php -h, --help (display this help notice)\n\n",0,1); 56 if ($args == '-h' OR $args == '--help') { 57 exit; 58 } else { 59 60 webcp_log(3,0,'webcp-httpd',"\n\n Running web://cp ".$cfg['webcp']." httpd daemon". 61 " interactively\n use ./webcp-httpd.php -h for help, CTRL-C to exit\n". 62 "==================================================\n\n",0,1); 63 $echo = 1; 64 } 65 } 66 unset($args); 67 /* get user uid and gid from username */ 68 if (!($user = posix_getpwnam($cfg['httpd_user'])) || !($group = posix_getgrgid($user['gid']))) { 69 webcp_log(0,0,'webcp-httpd',"User $cfg[httpd_user] does not exist.",0,$echo); 70 exit; 71 } 72 /* open a listening socket that is bound to an address and port */ 73 $lsocket = start_server(); 74 /* if ssl is on then start stunnel so we can accept ssl connections */ 75 if ($cfg['ssl']) { 76 switch ($cfg['osversion']) { 77 case 'RedHat9.0': 78 //spit out simple stunnel.conf file for redhat 9 79 $fp = fopen($cfg['basedir'].'/httpd/conf/stunnel4.conf', 'w'); 80 fwrite($fp, "######################################\n". 81 "# this file is auto generated by webcp\n". 82 "######################################\n\n". 83 "# permissions on cert should be set to 0600\n". 84 "cert = $cfg[ssl_cert]\n". 85 "setuid = $user[name]\n". 86 "setgid = $group[name]\n". 87 "output = /var/log/secure\n". 88 "pid = $cfg[httpsd_pid]\n\n". 89 "[webcp]\n". 90 "accept = $cfg[port]\n". 91 "TIMEOUTclose = 0\n". 92 "exec = $cfg[basedir]/server/ssl_in.php\n". 93 "\n"); 94 fclose($fp); 95 96 $stunnel = $cfg['prog']['stunnel']." $cfg[basedir]/httpd/conf/stunnel4.conf 2>&1"; 97 break; 98 default: 99 $stunnel = $cfg['prog']['stunnel'].' '. 100 "-p $cfg[ssl_cert] ". 101 "-d $cfg[listen_address]:$cfg[port] ". 102 "-l $cfg[basedir]/server/ssl_in.php ". 103 "-s $user[name] ". 104 "-g $group[name] ". 105 "-P $cfg[httpsd_pid] ". 106 "2>&1"; 107 } 108 /* run stunnel and exit on error */ 109 exec($stunnel, $stunnel_output, $stunnel_return); 110 if ($stunnel_return !== 0) { 111 webcp_log(0,0,'webcp-httpd',"stunnel had a problem.",0,$echo); 112 stop_server(); 113 } 114 webcp_log(2,0,'webcp-httpd',"stunnel is listening on port $cfg[port] and communicating with webcp through port $cfg[ssl_port]",0,$echo); 115 } 116 /* change to a user with lower permissions than root. We should do this as soon as possible. */ 117 posix_setgid($user['gid']); 118 posix_setuid($user['uid']); 119 /* define max length to use when reading from sockets/files */ 120 define("MAX_LENGTH", 4096); 121 /* php 4.3 pcntl doesn't work without ticks declaration */ 122 declare(ticks=1); 123 /* which functions should we run when we catch a posix signal 124 * stop_server() before shutdown, or run reload_server() on SIGHUP */ 125 pcntl_signal(SIGHUP, "reload_server"); // sig# 1 126 pcntl_signal(SIGINT, "stop_server"); // sig# 2 127 pcntl_signal(SIGTERM, "stop_server"); // sig# 15 128 /* increase our memory limit to 16 megabytes (standard is 8M) */ 129 ini_set('memory_limit', '16M'); 130 /* CLI automatically sets time limit to unlimited, but we need this for CGI */ 131 set_time_limit(0); 132 /* setup a database connection */ 133 db_connect($cfg['dbhost'], $cfg['dbname'], $cfg['dbuser'], $cfg['dbpass']); 134 /* fork the script into a background process */ 135 if ($echo === 0) { 136 $pid = pcntl_fork(); 137 if ($pid == -1) { 138 webcp_log(0,0,'webcp-httpd',"Failed to spawn a daemon",0,1); 139 exit; 140 } elseif ($pid) { 141 /* kill parent and return success */ 142 return 0; 143 } 144 /* become session leader / detach from the controlling terminal */ 145 if (!posix_setsid()) { 146 webcp_log(0,0,'webcp-httpd',"Could not detach from terminal",0,1); 147 exit; 148 } else 149 webcp_log(2,0,'webcp-httpd',"Webcp-httpd daemon has been started.",0,1); 150 } 151 /* create pid file */ 152 set_pid_file(getmypid()); 153 // an array mapping short http status strings to long http strings 154 $http_status_map=array( 155 "ok" => "200 OK", 156 "redirect" => "302 Found", 157 "forbidden" => "403 Forbidden", 158 "not found" => "404 Not Found", 159 "default" => "400 Bad Request" 160 ); 161 /* set some initial status variables */ 162 $httpd_status['started'] = get_microtime(); 163 $httpd_status['hits'] = 0; 164 $httpd_status['connections'] = 0; 165 $httpd_status['sent'] = 0; 166 /* initialize the client socket array */ 167 $csocket = array(); 168 /* enter an endless loop */ 169 while (true) { 170 /* close any sockets that have timed out */ 171 foreach($csocket as $slot => $socket) { 172 if (!empty($cfg['timeout']) && (get_microtime() - $cdata[$slot]['established']) > $cfg['timeout']) { 173 close_client($slot); 174 } elseif ($cfg['keep_alive'] && !$cfg['ssl']) { 175 if (get_microtime() > $cdata[$slot]['keep_alive']) { 176 close_client($slot); 177 } 178 } 179 } 180 /* build array consisting of sockets we want to get updates for */ 181 $set_r = array($lsocket); 182 $set_r = array_merge($set_r, $csocket); 183 /* $set_r will be an array holding the sockets that we have received data on. 184 * $ready will be the number of sockets that we have recieved data on. */ 185 $ready = @socket_select($set_r, $set_w = null, $set_e = null, $to_sec = 1); 186 if ($ready == 0 || $ready === false) { 187 /* there are zero updates on the listening socket, or we caught a posix signal */ 188 continue; 189 } 190 /* if there is an update on the listening socket create a new connection */ 191 if (in_array($lsocket, $set_r)) { 192 open_client($lsocket); 193 } 194 195 /* start loop over if there isn't anymore updated sockets */ 196 if ($ready-- <= 0) { 197 continue; 198 } 199 /* otherwise check client sockets for incoming data */ 200 foreach ($csocket as $slot => $socket) { 201 if (!in_array($socket, $set_r)) { 202 continue; 203 } 204 205 /* read data from the client into a buffer. if read fails close the connection */ 206 if (!$cdata[$slot]['buffer'] .= @socket_read($socket, MAX_LENGTH)) { 207 close_client($slot); 208 } else { 209 /* since we got a response, renew our keepalive timeout */ 210 if ($cfg['keep_alive'] && !$cfg['ssl']) { 211 $cdata[$slot]['keep_alive'] = get_microtime() + $cfg['keep_alive_timeout']; 212 } 213 /* check for http header double carriage return / line feed */ 214 if (!isset($cdata[$slot]['hlength'])) { 215 if (($cdata[$slot]['hlength'] = strpos($cdata[$slot]['buffer'], "\r\n\r\n")) !== false) { 216 $cdata[$slot]['hlength'] += 4; 217 /* According to what I've read in the HTTP RFC's (rfc1945, rfc2068, rfc2616) 218 * all client requests with a body, i.e. POSTs, are REQUIRED to have the 219 * Content-Length header. This would also apply for HTTP 1.1, despite 220 * chunking. So I guess we'll just make sure all the data arrived here. */ 221 if ($cdata[$slot]['clength'] = stristr($cdata[$slot]['buffer'], 'Content-Length:')) { 222 $cdata[$slot]['clength'] = substr($cdata[$slot]['clength'], 0, strpos($cdata[$slot]['clength'], "\r\n")); 223 $cdata[$slot]['clength'] = explode(':', $cdata[$slot]['clength']); 224 $cdata[$slot]['clength'] = trim($cdata[$slot]['clength'][1]); 225 } 226 if (!isset($cdata[$slot]['clength'])) 227 $cdata[$slot]['clength'] = 0; 228 } else { 229 /* we don't have a header length yet */ 230 continue; 231 } 232 } 233 /* If the full body content hasn't arrived yet, skip the next part. */ 234 if (strlen($cdata[$slot]['buffer']) < ($cdata[$slot]['hlength'] + $cdata[$slot]['clength'])) { 235 continue; 236 } 237 /* this is where we parse the request headers */ 238 $request = parse_request($cdata[$slot]['buffer']); 239 /* request has been parsed, erase the buffer. */ 240 $cdata[$slot]['buffer'] = ''; 241 unset($cdata[$slot]['hlength']); 242 unset($cdata[$slot]['clength']); 243 /* build response array based on the request array */ 244 $response = build_response($request); 245 246 /* then send our response */ 247 send_response($slot, $response, $request); 248 /* close the connection if we're done */ 249 if ($response['connection_close']) { 250 close_client($slot); 251 } 252 } 253 /* stop checking the client sockets if there isn't anymore updated sockets */ 254 if ($ready-- <= 0) { 255 break; 256 } 257 } 258 } 259 ?>
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
| [ Powered by PHPXref - Served by Debian GNU/Linux ] |