webjames.c 9.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330
  1. /*
  2. +----------------------------------------------------------------------+
  3. | PHP Version 5 |
  4. +----------------------------------------------------------------------+
  5. | Copyright (c) 1997-2016 The PHP Group |
  6. +----------------------------------------------------------------------+
  7. | This source file is subject to version 3.01 of the PHP license, |
  8. | that is bundled with this package in the file LICENSE, and is |
  9. | available through the world-wide-web at the following url: |
  10. | http://www.php.net/license/3_01.txt |
  11. | If you did not receive a copy of the PHP license and are unable to |
  12. | obtain it through the world-wide-web, please send a note to |
  13. | license@php.net so we can mail you a copy immediately. |
  14. +----------------------------------------------------------------------+
  15. | Author: Alex Waugh <alex@alexwaugh.com> |
  16. +----------------------------------------------------------------------+
  17. */
  18. #include "php.h"
  19. #include "SAPI.h"
  20. #include "php_main.h"
  21. #include "php_variables.h"
  22. #define WEBJAMES_PHP_ONLY
  23. #include "php_webjames.h"
  24. #include <unixlib/local.h>
  25. #define WEBJAMES_SAPI_VERSION "1.0.2"
  26. typedef struct {
  27. struct connection *conn; /*structure holding all the details of the current request*/
  28. int bodyread; /*amount of POST body read*/
  29. closefn oldclose; /*function to call to close the connection*/
  30. } php_webjames_globals;
  31. static php_webjames_globals webjames_globals;
  32. #define WG(v) (webjames_globals.v)
  33. static int sapi_webjames_ub_write(const char *str, uint str_length TSRMLS_DC)
  34. /*unbuffered write - send data straight out to socket*/
  35. {
  36. int totalbytes = 0;
  37. do {
  38. int bytes;
  39. bytes = webjames_writebuffer(WG(conn),str,str_length);
  40. if (bytes<0) {
  41. PG(connection_status) = PHP_CONNECTION_ABORTED;
  42. if (!PG(ignore_user_abort)) {
  43. zend_bailout();
  44. }
  45. return bytes;
  46. }
  47. str += bytes;
  48. str_length -= bytes;
  49. totalbytes += bytes;
  50. } while (str_length);
  51. return totalbytes;
  52. }
  53. static void sapi_webjames_send_header(sapi_header_struct *sapi_header, void *server_context TSRMLS_DC)
  54. /*send an HTTP header*/
  55. {
  56. char *header = sapi_header->header;
  57. int len = sapi_header->header_len;
  58. if (WG(conn)->flags.outputheaders) {
  59. while (sapi_header && len > 0) {
  60. int bytes;
  61. bytes = webjames_writebuffer(WG(conn), header, len);
  62. if (bytes<0) {
  63. PG(connection_status) = PHP_CONNECTION_ABORTED;
  64. if (!PG(ignore_user_abort)) {
  65. zend_bailout();
  66. }
  67. return;
  68. }
  69. header += bytes;
  70. len -= bytes;
  71. }
  72. webjames_writestring(WG(conn), "\r\n");
  73. }
  74. }
  75. static int sapi_webjames_read_post(char *buffer, uint count_bytes TSRMLS_DC)
  76. /*read some of the post data*/
  77. {
  78. if (WG(conn)->body==NULL) return 0;
  79. if (count_bytes+WG(bodyread)>WG(conn)->bodysize) count_bytes=WG(conn)->bodysize-WG(bodyread);
  80. memcpy(buffer, WG(conn)->body+WG(bodyread), count_bytes);
  81. WG(bodyread)+=count_bytes;
  82. return count_bytes;
  83. }
  84. static char *sapi_webjames_read_cookies(TSRMLS_D)
  85. {
  86. return WG(conn)->cookie;
  87. }
  88. #define BUF_SIZE 512
  89. #define ADD_STRING(name,string)\
  90. php_register_variable(name, string, track_vars_array TSRMLS_CC)
  91. #define ADD_NUM(name,field) {\
  92. snprintf(buf, BUF_SIZE, "%d", WG(conn)->field);\
  93. php_register_variable(name, buf, track_vars_array TSRMLS_CC);\
  94. }
  95. #define ADD_FIELD(name, field) \
  96. if (WG(conn)->field) { \
  97. php_register_variable(name, WG(conn)->field, track_vars_array TSRMLS_CC); \
  98. }
  99. static void sapi_webjames_register_variables(zval *track_vars_array TSRMLS_DC)
  100. {
  101. char buf[BUF_SIZE + 1];
  102. char *docroot;
  103. buf[BUF_SIZE] = '\0';
  104. ADD_STRING("SERVER_SOFTWARE", configuration.server);
  105. ADD_STRING("SERVER_NAME", configuration.serverip);
  106. ADD_FIELD("SERVER_PROTOCOL", protocol);
  107. ADD_NUM("SERVER_PORT", port);
  108. ADD_STRING("SERVER_ADMIN",configuration.webmaster);
  109. ADD_STRING("GATEWAY_INTERFACE", "CGI/1.1");
  110. docroot = __unixify(WG(conn)->homedir,0,NULL,1024,0);
  111. if (docroot) ADD_STRING("DOCUMENT_ROOT", docroot);
  112. ADD_FIELD("REQUEST_METHOD", methodstr);
  113. ADD_FIELD("REQUEST_URI", requesturi);
  114. ADD_STRING("PATH_TRANSLATED", SG(request_info).path_translated);
  115. ADD_FIELD("SCRIPT_NAME", uri);
  116. ADD_FIELD("PHP_SELF", uri);
  117. ADD_FIELD("QUERY_STRING", args);
  118. snprintf(buf, BUF_SIZE, "%d.%d.%d.%d", WG(conn)->ipaddr[0], WG(conn)->ipaddr[1], WG(conn)->ipaddr[2], WG(conn)->ipaddr[3]);
  119. ADD_STRING("REMOTE_ADDR", buf);
  120. if (WG(conn)->dnsstatus == DNS_OK) ADD_FIELD("REMOTE_HOST", host);
  121. if ((WG(conn)->method == METHOD_POST) || (WG(conn)->method == METHOD_PUT)) {
  122. ADD_NUM("CONTENT_LENGTH", bodysize);
  123. ADD_FIELD("CONTENT_TYPE", type);
  124. }
  125. if ((WG(conn)->method == METHOD_PUT) || (WG(conn)->method == METHOD_DELETE)) ADD_FIELD("ENTITY_PATH", requesturi);
  126. if (WG(conn)->pwd) {
  127. ADD_STRING("AUTH_TYPE", "basic");
  128. ADD_FIELD("REMOTE_USER", authorization);
  129. }
  130. ADD_FIELD("HTTP_COOKIE", cookie);
  131. ADD_FIELD("HTTP_USER_AGENT", useragent);
  132. ADD_FIELD("HTTP_REFERER", referer);
  133. ADD_FIELD("HTTP_ACCEPT", accept);
  134. ADD_FIELD("HTTP_ACCEPT_LANGUAGE", acceptlanguage);
  135. ADD_FIELD("HTTP_ACCEPT_CHARSET", acceptcharset);
  136. ADD_FIELD("HTTP_ACCEPT_ENCODING", acceptencoding);
  137. }
  138. static void webjames_module_main(TSRMLS_D)
  139. {
  140. zend_file_handle file_handle;
  141. FILE *fp=NULL;
  142. char *path;
  143. /* Convert filename to Unix format*/
  144. __riscosify_control|=__RISCOSIFY_STRICT_UNIX_SPECS;
  145. path = __unixify(WG(conn)->filename,0,NULL,1024,0);
  146. if (path) SG(request_info).path_translated = estrdup(path);
  147. SG(request_info).query_string = WG(conn)->args;
  148. SG(request_info).request_uri = WG(conn)->requesturi;
  149. SG(request_info).request_method = WG(conn)->methodstr;
  150. if (WG(conn)->method==METHOD_HEAD) {
  151. SG(request_info).headers_only = 1;
  152. } else {
  153. SG(request_info).headers_only = 0;
  154. }
  155. SG(sapi_headers).http_response_code = 200;
  156. SG(request_info).content_type = WG(conn)->type;
  157. SG(request_info).content_length = WG(conn)->bodysize;
  158. SG(request_info).auth_user = NULL;
  159. SG(request_info).auth_password = NULL;
  160. if (WG(conn)->authorization) {
  161. char *colon=strchr(WG(conn)->authorization,':');
  162. if (colon) {
  163. SG(request_info).auth_user = emalloc(colon-WG(conn)->authorization+1);
  164. if (SG(request_info).auth_user) {
  165. memcpy(SG(request_info).auth_user,WG(conn)->authorization,colon-WG(conn)->authorization);
  166. SG(request_info).auth_user[colon-WG(conn)->authorization]='\0';
  167. SG(request_info).auth_password = estrdup(colon+1);
  168. }
  169. }
  170. }
  171. /*ensure that syslog calls get logged separately from WebJames' main log */
  172. openlog("PHP",0,0);
  173. file_handle.type = ZEND_HANDLE_FILENAME;
  174. file_handle.filename = SG(request_info).path_translated;
  175. file_handle.free_filename = 0;
  176. file_handle.opened_path = NULL;
  177. if (php_request_startup(TSRMLS_C) == FAILURE) {
  178. return;
  179. }
  180. php_execute_script(&file_handle TSRMLS_CC);
  181. php_request_shutdown(NULL);
  182. }
  183. static void webjames_php_close(struct connection *conn, int force)
  184. /*called by webjames if it wants to close the connection*/
  185. {
  186. TSRMLS_FETCH();
  187. php_request_shutdown(NULL);
  188. WG(oldclose)(conn,force);
  189. }
  190. void webjames_php_request(struct connection *conn)
  191. /*called by WebJames to start handler*/
  192. {
  193. TSRMLS_FETCH();
  194. WG(conn) = conn;
  195. WG(bodyread) = 0;
  196. WG(oldclose) = conn->close;
  197. conn->close=webjames_php_close;
  198. webjames_module_main(TSRMLS_C);
  199. WG(oldclose)(WG(conn), 0);
  200. }
  201. static void php_info_webjames(ZEND_MODULE_INFO_FUNC_ARGS)
  202. {
  203. php_info_print_table_start();
  204. php_info_print_table_row(2, "SAPI module version", WEBJAMES_SAPI_VERSION);
  205. php_info_print_table_row(2, "WebJames version", WEBJAMES_VERSION " (" WEBJAMES_DATE ")");
  206. php_info_print_table_end();
  207. }
  208. static zend_module_entry php_webjames_module = {
  209. #if ZEND_MODULE_API_NO >= 20010901
  210. STANDARD_MODULE_HEADER,
  211. #endif
  212. "WebJames",
  213. NULL,
  214. NULL,
  215. NULL,
  216. NULL,
  217. NULL,
  218. php_info_webjames,
  219. #if ZEND_MODULE_API_NO >= 20010901
  220. WEBJAMES_SAPI_VERSION,
  221. #endif
  222. STANDARD_MODULE_PROPERTIES
  223. };
  224. static int php_webjames_startup(sapi_module_struct *sapi_module)
  225. {
  226. if(php_module_startup(sapi_module, &php_webjames_module, 1) == FAILURE) {
  227. return FAILURE;
  228. } else {
  229. return SUCCESS;
  230. }
  231. }
  232. static sapi_module_struct sapi_module = {
  233. "webjames", /* name */
  234. "WebJames", /* pretty name */
  235. php_webjames_startup, /* startup */
  236. php_module_shutdown_wrapper, /* shutdown */
  237. NULL, /* activate */
  238. NULL, /* deactivate */
  239. sapi_webjames_ub_write, /* unbuffered write */
  240. NULL, /* flush */
  241. NULL, /* get uid */
  242. NULL, /* getenv */
  243. php_error, /* error handler */
  244. NULL, /* header handler */
  245. NULL, /* send headers handler */
  246. sapi_webjames_send_header, /* send header handler */
  247. sapi_webjames_read_post, /* read POST data */
  248. sapi_webjames_read_cookies, /* read Cookies */
  249. sapi_webjames_register_variables, /* register server variables */
  250. NULL, /* Log message */
  251. NULL, /* Get request time */
  252. NULL, /* Child terminate */
  253. STANDARD_SAPI_MODULE_PROPERTIES
  254. };
  255. int webjames_php_init(void)
  256. /*called when WebJames initialises*/
  257. {
  258. TSRMLS_FETCH();
  259. if (strcmp(configuration.webjames_h_revision,WEBJAMES_H_REVISION)!=0) {
  260. /*This file was compiled against a different revision of
  261. webjames.h than webjames was, which could be bad news*/
  262. webjames_writelog(0,"PHP module is compiled for WebJames (%s) and was linked with a different version (%s)",WEBJAMES_H_REVISION,configuration.webjames_h_revision);
  263. return 0; /*failed to initialise*/
  264. }
  265. sapi_startup(&sapi_module);
  266. sapi_module.startup(&sapi_module);
  267. SG(server_context) = (void *) 1;
  268. return 1; /*initialised correctly*/
  269. }
  270. void webjames_php_shutdown(void)
  271. /*called when WebJames is about to quit*/
  272. {
  273. sapi_module.shutdown(&sapi_module);
  274. sapi_shutdown();
  275. }