[ PHPXref.com ] [ Generated: Sun Jul 20 21:01:33 2008 ] [ web-cp 0.5.7 ]
[ Index ]     [ Variables ]     [ Functions ]     [ Classes ]     [ Constants ]     [ Statistics ]

title

Body

[close]

/server/ -> webcp-httpd.php (source)

   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  ?>


[ Powered by PHPXref - Served by Debian GNU/Linux ]