PageRenderTime 49ms CodeModel.GetById 22ms RepoModel.GetById 0ms app.codeStats 0ms

/code/classes/Daemon/HTTPd/Client.class.php

https://github.com/blekkzor/pinetd2
PHP | 201 lines | 168 code | 26 blank | 7 comment | 20 complexity | ad9282a4f5ef1ca7d6beda9f673d7baf MD5 | raw file
Possible License(s): GPL-2.0
  1. <?php
  2. namespace Daemon\HTTPd;
  3. class Client extends \pinetd\TCP\Client {
  4. protected $header = array();
  5. protected $waitlen = 0;
  6. // outgoing stuff
  7. protected $headers_sent = false;
  8. protected $out_headers = array();
  9. public function welcomeUser() {
  10. return true;
  11. }
  12. public function sendBanner() {
  13. }
  14. public function getVersionString() {
  15. return $this->IPC->getVersionString();
  16. }
  17. protected function initRequest($request, $headers, $cookies, $post = NULL) {
  18. $this->headers_sent = false;
  19. $this->out_headers = array();
  20. $this->header('Server: '.$this->getVersionString());
  21. $this->header('Content-Type: text/html');
  22. ob_start(array($this, '_outputHandler'));
  23. $path = parse_url($request['path']);
  24. // build vars for $_SERVER
  25. $s_vars = array(
  26. 'REMOTE_ADDR' => $this->peer[0],
  27. 'SERVER_SIGNATURE' => $this->getVersionString(),
  28. 'SERVER_SOFTWARE' => 'PInetd',
  29. 'DOCUMENT_ROOT' => $base,
  30. 'REMOTE_PORT' => $this->peer[1],
  31. 'GATEWAY_INTERFACE' => 'CGI/1.1',
  32. 'SERVER_PROTOCOL' => 'HTTP/'.$request['version'],
  33. 'REQUEST_METHOD' => $request['method'],
  34. 'QUERY_STRING' => $path['query'],
  35. 'REQUEST_URI' => $request['path'],
  36. 'SCRIPT_NAME' => $path['path'],
  37. 'PHP_SELF' => $path['path'],
  38. );
  39. foreach($headers as $head => $data) {
  40. $head = 'HTTP_'.preg_replace('/[^A-Z0-9_]/', '_', strtoupper($head));
  41. $s_vars[$head] = $data[0][1];
  42. }
  43. // GET
  44. $g_vars = array();
  45. parse_str((string)$path['query'], $g_vars);
  46. $context = array(
  47. '_SERVER' => $s_vars,
  48. '_GET' => $g_vars,
  49. '_COOKIE' => $cookies,
  50. );
  51. $this->handleRequest($path['path'], $context);
  52. if (isset($context['_SESSION_ID'])) $this->IPC->setSession($context['_SESSION_ID'], serialize($context['_SESSION']));
  53. ob_end_flush();
  54. $this->close();
  55. }
  56. protected function setCookie($cookie, $value) {
  57. $this->header('Set-Cookie: '.urlencode($cookie).'='.urlencode($value), false);
  58. }
  59. protected function sessionStart(array &$context) {
  60. if (isset($context['_COOKIE']['SESSID'])) {
  61. $session = $this->IPC->getSession($context['_COOKIE']['SESSID']);
  62. if (!is_null($session)) {
  63. $context['_SESSION_ID'] = $context['_COOKIE']['SESSID'];
  64. $context['_SESSION'] = unserialize($session);
  65. return true;
  66. }
  67. }
  68. $context['_SESSION_ID'] = $this->IPC->createSession();
  69. $context['_SESSION'] = array();
  70. $this->setCookie('SESSID', $context['_SESSION_ID']);
  71. return true;
  72. }
  73. public function header($head, $replace = true) {
  74. $pos = strpos($head, ':');
  75. if ($pos === false) return;
  76. $type = strtolower(substr($head, 0, $pos));
  77. if ($replace) {
  78. $this->out_headers[$type] = array($head);
  79. } else {
  80. $this->out_headers[$type][] = $head;
  81. }
  82. }
  83. public function _outputHandler($str) {
  84. // check if headers sent
  85. if (!$this->headers_sent) {
  86. $headers = 'HTTP/1.0 200 Ok'."\r\n";
  87. // build headers
  88. foreach($this->out_headers as $type => $list) {
  89. foreach($list as $head)
  90. $headers .= $head . "\r\n";
  91. }
  92. $this->sendMsg($headers."\r\n");
  93. $this->headers_sent = true;
  94. }
  95. $this->sendMsg($str);
  96. return '';
  97. }
  98. protected function handleRequest($path, &$context) {
  99. //var_dump($request, $headers, $cookies);
  100. $answer = new HTTPAnswerError($this);
  101. $answer->send(HTTPAnswerError::NOT_FOUND);
  102. }
  103. protected function decodeRequest($data = null) {
  104. // parse request headers
  105. $cookies = array();
  106. $headers = array();
  107. foreach($this->header as $id => $head) {
  108. if ($id == 0) {
  109. $request = $head;
  110. continue;
  111. }
  112. $pos = strpos($head, ':');
  113. if ($pos === false) {
  114. $answer = new HTTPAnswerError($this);
  115. $answer->send(HTTPAnswerError::BAD_REQUEST);
  116. $this->close();
  117. return;
  118. }
  119. $var = substr($head, 0, $pos);
  120. $val = ltrim(substr($head, $pos+1));
  121. $key = strtolower($var);
  122. if ($key == 'cookie') {
  123. $val = explode(';', $val);
  124. foreach($val as $cook) {
  125. $pos = strpos($cook, '=');
  126. if ($pos === false) {
  127. $answer = new HTTPAnswerError($this);
  128. $answer->send(HTTPAnswerError::BAD_REQUEST);
  129. $this->close();
  130. return;
  131. }
  132. $var = urldecode(trim(substr($cook, 0, $pos)));
  133. $val = urldecode(trim(substr($cook, $pos+1)));
  134. $cookies[$var] = $val;
  135. }
  136. continue;
  137. }
  138. $headers[$key][] = array($var, $val);
  139. }
  140. if (preg_match('#^([A-Z]+) ([^ ]+) HTTP/(1\.[01])$#', $request, $match) == 0) {
  141. $answer = new HTTPAnswerError($this);
  142. $answer->send(HTTPAnswerError::BAD_REQUEST);
  143. $this->close();
  144. return;
  145. }
  146. $request = array(
  147. 'method' => $match[1],
  148. 'path' => $match[2],
  149. 'version' => $match[3],
  150. );
  151. $this->initRequest($request, $headers, $cookies);
  152. }
  153. protected function parseBuffer() {
  154. while($this->ok) {
  155. if ($this->waitlen > 0) {
  156. if (strlen($this->buf) < $this->waitlen) return;
  157. $data = substr($this->buf, 0, $this->waitlen);
  158. $this->buf = substr($this->buf, $this->waitlen);
  159. $this->initRequest($request, $headers, $cookies, $data);
  160. continue;
  161. }
  162. $pos = strpos($this->buf, "\n");
  163. if ($pos === false) return; // no request yet
  164. $pos++;
  165. $lin = substr($this->buf, 0, $pos);
  166. $this->buf = substr($this->buf, $pos);
  167. $lin = rtrim($lin);
  168. if ($lin == '') {
  169. $this->decodeRequest();
  170. continue;
  171. }
  172. $this->header[] = $lin;
  173. }
  174. }
  175. }