Created
February 20, 2011 04:35
-
-
Save moriyoshi/835698 to your computer and use it in GitHub Desktop.
Revisions
-
moriyoshi revised this gist
Mar 6, 2011 . 1 changed file with 3 additions and 1 deletion.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -1636,7 +1636,7 @@ Index: sapi/cli/php_cli_server.c =================================================================== --- sapi/cli/php_cli_server.c (revision 0) +++ sapi/cli/php_cli_server.c (revision 0) @@ -0,0 +1,2083 @@ +/* + +----------------------------------------------------------------------+ + | PHP Version 5 | @@ -2218,6 +2218,7 @@ Index: sapi/cli/php_cli_server.c + if (mode & POLLOUT) { + PHP_SAFE_FD_CLR(fd, &poller->wfds); + } +#ifndef PHP_WIN32 + if (fd == poller->max_fd) { + while (fd > 0) { + fd--; @@ -2228,6 +2229,7 @@ Index: sapi/cli/php_cli_server.c + } + poller->max_fd = fd; + } +#endif +} /* }}} */ + +static int php_cli_server_poller_poll(php_cli_server_poller *poller, const struct timeval *tv) /* {{{ */ -
moriyoshi revised this gist
Mar 6, 2011 . 1 changed file with 19 additions and 17 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -1636,7 +1636,7 @@ Index: sapi/cli/php_cli_server.c =================================================================== --- sapi/cli/php_cli_server.c (revision 0) +++ sapi/cli/php_cli_server.c (revision 0) @@ -0,0 +1,2081 @@ +/* + +----------------------------------------------------------------------+ + | PHP Version 5 | @@ -1734,9 +1734,9 @@ Index: sapi/cli/php_cli_server.c + +typedef struct php_cli_server_poller { + fd_set rfds, wfds; + struct { + fd_set rfds, wfds; + } active; + php_socket_t max_fd; +} php_cli_server_poller; + @@ -2155,11 +2155,6 @@ Index: sapi/cli/php_cli_server.c + fprintf(stderr, "[%s] %s\n", buf, msg); +} /* }}} */ + +/* {{{ sapi_module_struct cli_server_sapi_module + */ +sapi_module_struct cli_server_sapi_module = { @@ -2188,7 +2183,7 @@ Index: sapi/cli/php_cli_server.c + + sapi_cli_server_register_variables, /* register server variables */ + sapi_cli_server_log_message, /* Log message */ + NULL, /* Get request time */ + NULL, /* Child terminate */ + + STANDARD_SAPI_MODULE_PROPERTIES @@ -2248,21 +2243,21 @@ Index: sapi/cli/php_cli_server.c +#ifdef PHP_WIN32 + struct socket_entry { + SOCKET fd; + int events; + } entries[FD_SETSIZE * 2]; + php_socket_t fd = 0; + size_t i; + struct socket_entry *n = entries, *m; + + for (i = 0; i < poller->active.rfds.fd_count; i++) { + n->events = POLLIN; + n->fd = poller->active.rfds.fd_array[i]; + n++; + } + + m = n; + for (i = 0; i < poller->active.wfds.fd_count; i++) { + struct socket_entry *e; + SOCKET fd = poller->active.wfds.fd_array[i]; + for (e = entries; e < m; e++) { + if (e->fd == fd) { @@ -2273,7 +2268,7 @@ Index: sapi/cli/php_cli_server.c + assert(n < entries + FD_SETSIZE * 2); + n->events = POLLOUT; + n->fd = fd; + n++; + } + } + @@ -2291,7 +2286,7 @@ Index: sapi/cli/php_cli_server.c + const php_socket_t max_fd = poller->max_fd; + const unsigned int *pr = (unsigned int *)&poller->active.rfds, + *pw = (unsigned int *)&poller->active.wfds, + *e = pr + (max_fd + (8 * sizeof(unsigned int)) - 1) / (8 * sizeof(unsigned int)); + unsigned int mask; + while (pr < e && fd <= max_fd) { + for (mask = 1; mask; mask <<= 1, fd++) { @@ -2580,6 +2575,13 @@ Index: sapi/cli/php_cli_server.c + continue; + } + +#ifdef SO_REUSEADDR + { + int val = 1; + setsockopt(retval, SOL_SOCKET, SO_REUSEADDR, (char*)&val, sizeof(val)); + } +#endif + + if (bind(retval, sa, *socklen) == SOCK_CONN_ERR) { + err = php_socket_errno(); + if (err == SOCK_EINVAL || err == SOCK_EADDRINUSE) { -
moriyoshi revised this gist
Mar 3, 2011 . 1 changed file with 2 additions and 2 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -3182,7 +3182,7 @@ Index: sapi/cli/php_cli_server.c + goto fail; + } + append_essential_headers(&buffer, client, 1); + smart_str_appends_ex(&buffer, "Content-Type: text/html; charset=UTF-8\r\n", 1); + smart_str_appends_ex(&buffer, "Content-Length: ", 1); + smart_str_append_generic_ex(&buffer, php_cli_server_buffer_size(&client->content_sender.buffer), 1, size_t, _unsigned); + smart_str_appendl_ex(&buffer, "\r\n", 2, 1); @@ -3277,7 +3277,7 @@ Index: sapi/cli/php_cli_server.c + smart_str_appendl_ex(&buffer, "Content-Type: ", sizeof("Content-Type: ") - 1, 1); + smart_str_appends_ex(&buffer, mime_type, 1); + if (strncmp(mime_type, "text/", 5) == 0) { + smart_str_appends_ex(&buffer, "; charset=UTF-8", 1); + } + smart_str_appendl_ex(&buffer, "\r\n", 2, 1); + smart_str_appends_ex(&buffer, "Content-Length: ", 1); -
moriyoshi revised this gist
Mar 2, 2011 . 1 changed file with 209 additions and 132 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -2,29 +2,21 @@ Index: sapi/cli/config.w32 =================================================================== --- sapi/cli/config.w32 (revision 308839) +++ sapi/cli/config.w32 (working copy) @@ -6,7 +6,8 @@ ARG_ENABLE('cli-win32', 'Build console-less CLI version of PHP', 'no'); if (PHP_CLI == "yes") { - SAPI('cli', 'php_cli.c', 'php.exe'); + SAPI('cli', 'php_cli.c php_http_parser.c php_cli_server.c', 'php.exe'); + ADD_FLAG("LIBS_CLI", "ws2_32.lib"); if (PHP_CRT_DEBUG == "yes") { ADD_FLAG("CFLAGS_CLI", "/D PHP_WIN32_DEBUG_HEAP"); } Index: sapi/cli/php_http_parser.c =================================================================== --- sapi/cli/php_http_parser.c (revision 0) +++ sapi/cli/php_http_parser.c (revision 0) @@ -0,0 +1,1602 @@ +/* Copyright 2009,2010 Ryan Dahl <[email protected]> + * + * Permission is hereby granted, free of charge, to any person obtaining a copy @@ -357,13 +349,6 @@ Index: sapi/cli/php_http_parser.c + uint64_t index = parser->index; + uint64_t nread = parser->nread; + + /* technically we could combine all of these (except for url_mark) into one + variable, saving stack space, but it seems more clear to have them + separated. */ @@ -374,6 +359,13 @@ Index: sapi/cli/php_http_parser.c + const char *path_mark = 0; + const char *url_mark = 0; + + if (len == 0) { + if (state == s_body_identity_eof) { + CALLBACK2(message_complete); + } + return 0; + } + + if (state == s_header_field) + header_field_mark = data; + if (state == s_header_value) @@ -622,10 +614,11 @@ Index: sapi/cli/php_http_parser.c + + case s_req_method: + { + const char *matcher; + if (ch == '\0') + goto error; + + matcher = method_strings[parser->method]; + if (ch == ' ' && matcher[index] == '\0') { + state = s_req_spaces_before_url; + } else if (ch == matcher[index]) { @@ -1643,7 +1636,7 @@ Index: sapi/cli/php_cli_server.c =================================================================== --- sapi/cli/php_cli_server.c (revision 0) +++ sapi/cli/php_cli_server.c (revision 0) @@ -0,0 +1,2079 @@ +/* + +----------------------------------------------------------------------+ + | PHP Version 5 | @@ -1666,7 +1659,6 @@ Index: sapi/cli/php_cli_server.c + +#include <stdio.h> +#include <fcntl.h> +#include <assert.h> + +#ifdef PHP_WIN32 @@ -1742,6 +1734,9 @@ Index: sapi/cli/php_cli_server.c + +typedef struct php_cli_server_poller { + fd_set rfds, wfds; + struct { + fd_set rfds, wfds; + } active; + php_socket_t max_fd; +} php_cli_server_poller; + @@ -1820,7 +1815,7 @@ Index: sapi/cli/php_cli_server.c + char *router; + size_t router_len; + socklen_t socklen; + HashTable clients; +} php_cli_server; + +typedef struct php_cli_server_http_reponse_status_code_pair { @@ -1877,8 +1872,8 @@ Index: sapi/cli/php_cli_server.c +}; + +static php_cli_server_http_reponse_status_code_pair template_map[] = { + { 404, "<h1 class=\"h\">%s</h1><p>The requested resource %s was not found on this server.</p>" }, + { 500, "<h1 class=\"h\">%s</h1><p>The server is temporality unavaiable.</p>" } +}; + +static php_cli_server_ext_mime_type_pair mime_type_map[] = { @@ -1906,16 +1901,7 @@ Index: sapi/cli/php_cli_server.c + +static char *get_last_error() /* {{{ */ +{ + return pestrdup(strerror(errno), 1); +} /* }}} */ + +static const char *get_status_string(int code) /* {{{ */ @@ -2249,11 +2235,78 @@ Index: sapi/cli/php_cli_server.c + } +} /* }}} */ + +static int php_cli_server_poller_poll(php_cli_server_poller *poller, const struct timeval *tv) /* {{{ */ +{ + memcpy(&poller->active.rfds, &poller->rfds, sizeof(poller->rfds)); + memcpy(&poller->active.wfds, &poller->wfds, sizeof(poller->wfds)); + return php_select(poller->max_fd + 1, &poller->active.rfds, &poller->active.wfds, NULL, (struct timeval *)tv); +} /* }}} */ + +static int php_cli_server_poller_iter_on_active(php_cli_server_poller *poller, void *opaque, int(*callback)(void *, int fd, int events)) /* {{{ */ +{ + int retval = SUCCESS; +#ifdef PHP_WIN32 + struct socket_entry { + SOCKET fd; + int events; + } entries[FD_SETSIZE * 2]; + php_socket_t fd = 0; + size_t i; + struct socket_entry *n = entries, *m; + + for (i = 0; i < poller->active.rfds.fd_count; i++) { + n->events = POLLIN; + n->fd = poller->active.rfds.fd_array[i]; + n++; + } + + m = n; + for (i = 0; i < poller->active.wfds.fd_count; i++) { + struct socket_entry *e; + SOCKET fd = poller->active.wfds.fd_array[i]; + for (e = entries; e < m; e++) { + if (e->fd == fd) { + e->events |= POLLOUT; + } + } + if (e == m) { + assert(n < entries + FD_SETSIZE * 2); + n->events = POLLOUT; + n->fd = fd; + n++; + } + } + + { + struct socket_entry *e = entries; + for (; e < n; e++) { + if (SUCCESS != callback(opaque, e->fd, e->events)) { + retval = FAILURE; + } + } + } + +#else + php_socket_t fd = 0; + const php_socket_t max_fd = poller->max_fd; + const unsigned int *pr = (unsigned int *)&poller->active.rfds, + *pw = (unsigned int *)&poller->active.wfds, + *e = pr + (max_fd + (8 * sizeof(unsigned int)) - 1) / (8 * sizeof(unsigned int)); + unsigned int mask; + while (pr < e && fd <= max_fd) { + for (mask = 1; mask; mask <<= 1, fd++) { + int events = (*pr & mask ? POLLIN: 0) | (*pw & mask ? POLLOUT: 0); + if (events) { + if (SUCCESS != callback(opaque, fd, events)) { + retval = FAILURE; + } + } + } + pr++; + pw++; + } +#endif + return retval; +} /* }}} */ + +static size_t php_cli_server_chunk_size(const php_cli_server_chunk *chunk) /* {{{ */ @@ -2389,8 +2442,8 @@ Index: sapi/cli/php_cli_server.c + size_t _nbytes_sent_total = 0; + + for (chunk = sender->buffer.first; chunk; chunk = next) { + ssize_t nbytes_sent; + next = chunk->next; + + switch (chunk->type) { + case PHP_CLI_SERVER_CHUNK_HEAP: @@ -2475,7 +2528,7 @@ Index: sapi/cli/php_cli_server.c + +static int php_network_listen_socket(const char *host, int *port, int socktype, int *af, socklen_t *socklen, char **errstr TSRMLS_DC) /* {{{ */ +{ + int retval = SOCK_ERR; + int err = 0; + struct sockaddr *sa = NULL, **p, **sal; + @@ -2499,11 +2552,11 @@ Index: sapi/cli/php_cli_server.c + sa = pemalloc(sizeof(struct sockaddr_in6), 1); + if (!sa) { + closesocket(retval); + retval = SOCK_ERR; + *errstr = NULL; + goto out; + } + *(struct sockaddr_in6 *)sa = *(struct sockaddr_in6 *)*p; + ((struct sockaddr_in6 *)sa)->sin6_port = htons(*port); + *socklen = sizeof(struct sockaddr_in6); + break; @@ -2512,11 +2565,11 @@ Index: sapi/cli/php_cli_server.c + sa = pemalloc(sizeof(struct sockaddr_in), 1); + if (!sa) { + closesocket(retval); + retval = SOCK_ERR; + *errstr = NULL; + goto out; + } + *(struct sockaddr_in *)sa = *(struct sockaddr_in *)*p; + ((struct sockaddr_in *)sa)->sin_port = htons(*port); + *socklen = sizeof(struct sockaddr_in); + break; @@ -2533,6 +2586,7 @@ Index: sapi/cli/php_cli_server.c + goto out; + } + closesocket(retval); + retval = SOCK_ERR; + continue; + } + err = 0; @@ -2558,6 +2612,10 @@ Index: sapi/cli/php_cli_server.c + break; + } + + if (retval == SOCK_ERR) { + goto out; + } + + if (listen(retval, SOMAXCONN)) { + err = php_socket_errno(); + goto out; @@ -2577,7 +2635,7 @@ Index: sapi/cli/php_cli_server.c + if (errstr) { + *errstr = php_socket_strerror(err, NULL, 0); + } + return SOCK_ERR; + } + return retval; +} /* }}} */ @@ -3046,11 +3104,7 @@ Index: sapi/cli/php_cli_server.c +#ifdef DEBUG + php_cli_server_logf("%s: Closing" TSRMLS_CC, client->addr_str); +#endif + zend_hash_index_del(&server->clients, client->sock); +} /* }}} */ + +static int php_cli_server_send_error_page(php_cli_server *server, php_cli_server_client *client, int status TSRMLS_DC) /* {{{ */ @@ -3067,12 +3121,12 @@ Index: sapi/cli/php_cli_server.c + escaped_request_uri = php_escape_html_entities_ex((unsigned char *)client->request.request_uri, client->request.request_uri_len, &escaped_request_uri_len, 0, ENT_QUOTES, NULL, 0 TSRMLS_CC); + + { + static const char prologue_template[] = "<html><head><title>%d %s</title>"; + php_cli_server_chunk *chunk = php_cli_server_chunk_heap_new_self_contained(strlen(prologue_template) + 3 + strlen(status_string) + 1); + if (!chunk) { + goto fail; + } + snprintf(chunk->data.heap.p, chunk->data.heap.len, prologue_template, status, status_string, escaped_request_uri); + chunk->data.heap.len = strlen(chunk->data.heap.p); + php_cli_server_buffer_append(&client->content_sender.buffer, chunk); + } @@ -3106,7 +3160,7 @@ Index: sapi/cli/php_cli_server.c + if (!chunk) { + goto fail; + } + snprintf(chunk->data.heap.p, chunk->data.heap.len, content_template, status_string, escaped_request_uri); + chunk->data.heap.len = strlen(chunk->data.heap.p); + php_cli_server_buffer_append(&client->content_sender.buffer, chunk); + } @@ -3326,17 +3380,7 @@ Index: sapi/cli/php_cli_server.c + +static void php_cli_server_dtor(php_cli_server *server TSRMLS_DC) /* {{{ */ +{ + zend_hash_destroy(&server->clients); + if (server->server_sock >= 0) { + closesocket(server->server_sock); + } @@ -3351,6 +3395,14 @@ Index: sapi/cli/php_cli_server.c + } +} /* }}} */ + +static void php_cli_server_client_dtor_wrapper(php_cli_server_client **p) /* {{{ */ +{ + closesocket((*p)->sock); + php_cli_server_poller_remove(&(*p)->server->poller, POLLIN | POLLOUT, (*p)->sock); + php_cli_server_client_dtor(*p); + pefree(*p, 1); +} /* }}} */ + +static int php_cli_server_ctor(php_cli_server *server, const char *addr, const char *document_root, const char *router TSRMLS_DC) /* {{{ */ +{ + int retval = SUCCESS; @@ -3360,7 +3412,7 @@ Index: sapi/cli/php_cli_server.c + char *_router = NULL; + int err = 0; + int port = 3000; + php_socket_t server_sock = SOCK_ERR; + + host = pestrdup(addr, 1); + if (!host) { @@ -3376,7 +3428,7 @@ Index: sapi/cli/php_cli_server.c + } + + server_sock = php_network_listen_socket(host, &port, SOCK_STREAM, &server->address_family, &server->socklen, &errstr TSRMLS_CC); + if (server_sock == SOCK_ERR) { + php_cli_server_logf("Failed to listen on %s:%d (reason: %s)" TSRMLS_CC, host, port, errstr ? errstr: "?"); + efree(errstr); + retval = FAILURE; @@ -3394,12 +3446,7 @@ Index: sapi/cli/php_cli_server.c + server->host = host; + server->port = port; + + zend_hash_init(&server->clients, 0, NULL, (void(*)(void*))php_cli_server_client_dtor_wrapper, 1); + + { + size_t document_root_len = strlen(document_root); @@ -3495,71 +3542,93 @@ Index: sapi/cli/php_cli_server.c +} +/* }}} */ + +typedef struct php_cli_server_do_event_for_each_fd_callback_params { +#ifdef ZTS + void ***tsrm_ls; +#endif + php_cli_server *server; + int(*rhandler)(php_cli_server*, php_cli_server_client* TSRMLS_DC); + int(*whandler)(php_cli_server*, php_cli_server_client* TSRMLS_DC); +} php_cli_server_do_event_for_each_fd_callback_params; + +static int php_cli_server_do_event_for_each_fd_callback(void *_params, int fd, int event) +{ + php_cli_server_do_event_for_each_fd_callback_params *params = _params; +#ifdef ZTS + void ***tsrm_ls = params->tsrm_ls; +#endif + php_cli_server *server = params->server; + if (server->server_sock == fd) { + php_cli_server_client *client = NULL; + php_socket_t client_sock; + socklen_t socklen = server->socklen; + struct sockaddr *sa = pemalloc(server->socklen, 1); + if (!sa) { + return FAILURE; + } + client_sock = accept(server->server_sock, sa, &socklen); + if (client_sock < 0) { + char *errstr; + errstr = php_socket_strerror(php_socket_errno(), NULL, 0); + php_cli_server_logf("Failed to accept a client (reason: %s)" TSRMLS_CC, errstr); + efree(errstr); + pefree(sa, 1); + return SUCCESS; + } + if (SUCCESS != php_set_sock_blocking(client_sock, 0 TSRMLS_CC)) { + pefree(sa, 1); + closesocket(client_sock); + return SUCCESS; + } + if (!(client = pemalloc(sizeof(php_cli_server_client), 1)) || FAILURE == php_cli_server_client_ctor(client, server, client_sock, sa, socklen TSRMLS_CC)) { + php_cli_server_logf("Failed to create a new request object" TSRMLS_CC); + pefree(sa, 1); + closesocket(client_sock); + return SUCCESS; + } +#ifdef DEBUG + php_cli_server_logf("%s: Accepted" TSRMLS_CC, client->addr_str); +#endif + zend_hash_index_update(&server->clients, client_sock, &client, sizeof(client), NULL); + php_cli_server_recv_event_read_request(server, client TSRMLS_CC); + } else { + php_cli_server_client **client; + if (SUCCESS == zend_hash_index_find(&server->clients, fd, (void **)&client)) { + if (event & POLLIN) { + params->rhandler(server, *client TSRMLS_CC); + } + if (event & POLLOUT) { + params->whandler(server, *client TSRMLS_CC); + } + } + } + return SUCCESS; +} + +static void php_cli_server_do_event_for_each_fd(php_cli_server *server, int(*rhandler)(php_cli_server*, php_cli_server_client* TSRMLS_DC), int(*whandler)(php_cli_server*, php_cli_server_client* TSRMLS_DC) TSRMLS_DC) /* {{{ */ +{ + php_cli_server_do_event_for_each_fd_callback_params params = { +#ifdef ZTS + tsrm_ls, +#endif + server, + rhandler, + whandler + }; + + php_cli_server_poller_iter_on_active(&server->poller, ¶ms, php_cli_server_do_event_for_each_fd_callback); +} /* }}} */ + +static int php_cli_server_do_event_loop(php_cli_server *server TSRMLS_DC) /* {{{ */ +{ + int retval = SUCCESS; + while (server->is_running) { + static const struct timeval tv = { 1, 0 }; + int n = php_cli_server_poller_poll(&server->poller, &tv); + if (n > 0) { + php_cli_server_do_event_for_each_fd(server, + php_cli_server_recv_event_read_request, + php_cli_server_send_event TSRMLS_CC); + } else if (n == 0) { + /* do nothing */ + } else { @@ -3881,16 +3950,18 @@ Index: sapi/cli/php_cli.c =================================================================== --- sapi/cli/php_cli.c (revision 308839) +++ sapi/cli/php_cli.c (working copy) @@ -84,6 +84,10 @@ #include "php_getopt.h" +#ifndef PHP_CLI_WIN32_NO_CONSOLE +#include "php_cli_server.h" +#endif + #ifndef PHP_WIN32 # define php_select(m, r, w, e, t) select(m, r, w, e, t) #else @@ -126,10 +130,8 @@ "max_execution_time=0\n" "max_input_time=-1\n\0"; @@ -3902,15 +3973,15 @@ Index: sapi/cli/php_cli.c {'a', 0, "interactive"}, {'B', 1, "process-begin"}, {'C', 0, "no-chdir"}, /* for compatibility with CGI (do not chdir to script directory) */ @@ -150,6 +152,7 @@ {'r', 1, "run"}, {'s', 0, "syntax-highlight"}, {'s', 0, "syntax-highlighting"}, + {'S', 1, "server"}, {'w', 0, "strip"}, {'?', 0, "usage"},/* help alias (both '?' and 'usage') */ {'v', 0, "version"}, @@ -172,7 +175,7 @@ static int print_module_info(zend_module_entry *module TSRMLS_DC) /* {{{ */ { @@ -3919,7 +3990,7 @@ Index: sapi/cli/php_cli.c return ZEND_HASH_APPLY_KEEP; } /* }}} */ @@ -202,7 +205,7 @@ static int print_extension_info(zend_extension *ext, void *arg TSRMLS_DC) /* {{{ */ { @@ -3928,7 +3999,7 @@ Index: sapi/cli/php_cli.c return ZEND_HASH_APPLY_KEEP; } /* }}} */ @@ -494,7 +497,7 @@ prog = "php"; } @@ -3937,7 +4008,7 @@ Index: sapi/cli/php_cli.c " %s [options] -r <code> [--] [args...]\n" " %s [options] [-B <begin_code>] -R <code> [-E <end_code>] [--] [args...]\n" " %s [options] [-B <begin_code>] -F <file> [-E <end_code>] [--] [args...]\n" @@ -650,689 +653,708 @@ } /* }}} */ @@ -5134,9 +5205,11 @@ Index: sapi/cli/php_cli.c - } + break; + } +#ifndef PHP_CLI_WIN32_NO_CONSOLE + case 'S': + sapi_module = &cli_server_sapi_module; + break; +#endif + case 'h': /* help & quit */ + case '?': + php_cli_usage(argv[0]); @@ -5175,14 +5248,18 @@ Index: sapi/cli/php_cli.c + module_started = 1; + + zend_first_try { +#ifndef PHP_CLI_WIN32_NO_CONSOLE + if (sapi_module == &cli_sapi_module) { +#endif + ini_entries_len += sizeof(HARDCODED_INI) - 2; + ini_entries = realloc(ini_entries, ini_entries_len + sizeof(HARDCODED_INI)); + memcpy(ini_entries, HARDCODED_INI, sizeof(HARDCODED_INI)); + exit_status = do_cli(argc, argv TSRMLS_CC); +#ifndef PHP_CLI_WIN32_NO_CONSOLE + } else { + exit_status = do_cli_server(argc, argv TSRMLS_CC); + } +#endif } zend_end_try(); - out: @@ -5207,7 +5284,7 @@ Index: sapi/cli/php_cli.c if (module_started) { php_module_shutdown(TSRMLS_C); } @@ -1342,12 +1364,6 @@ #endif exit(exit_status); -
moriyoshi revised this gist
Mar 2, 2011 . 1 changed file with 41 additions and 231 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -1,22 +1,22 @@ Index: sapi/cli/config.w32 =================================================================== --- sapi/cli/config.w32 (revision 308839) +++ sapi/cli/config.w32 (working copy) @@ -6,7 +6,7 @@ ARG_ENABLE('cli-win32', 'Build console-less CLI version of PHP', 'no'); if (PHP_CLI == "yes") { - SAPI('cli', 'php_cli.c', 'php.exe'); + SAPI('cli', 'php_cli.c php_http_parser.c php_cli_server.c', 'php.exe'); if (PHP_CRT_DEBUG == "yes") { ADD_FLAG("CFLAGS_CLI", "/D PHP_WIN32_DEBUG_HEAP"); } @@ -14,7 +14,7 @@ } if (PHP_CLI_WIN32 == "yes") { - SAPI('cli_win32', 'cli_win32.c', 'php-win.exe'); + SAPI('cli_win32', 'cli_win32.c php_http_parser.c php_cli_server.c', 'php-win.exe'); ADD_FLAG("LDFLAGS_CLI_WIN32", "/stack:8388608"); } @@ -1628,14 +1628,14 @@ Index: sapi/cli/php_http_parser.c +} Index: sapi/cli/config.m4 =================================================================== --- sapi/cli/config.m4 (revision 308839) +++ sapi/cli/config.m4 (working copy) @@ -14,7 +14,7 @@ SAPI_CLI_PATH=sapi/cli/php dnl Select SAPI - PHP_SELECT_SAPI(cli, program, php_cli.c,, '$(SAPI_CLI_PATH)') + PHP_SELECT_SAPI(cli, program, php_cli.c php_http_parser.c php_cli_server.c,, '$(SAPI_CLI_PATH)') case $host_alias in *aix*) @@ -3879,9 +3879,9 @@ Index: sapi/cli/php_cli_server.h + */ Index: sapi/cli/php_cli.c =================================================================== --- sapi/cli/php_cli.c (revision 308839) +++ sapi/cli/php_cli.c (working copy) @@ -84,6 +84,8 @@ #include "php_getopt.h" @@ -3890,31 +3890,27 @@ Index: sapi/cli/php_cli.c #ifndef PHP_WIN32 # define php_select(m, r, w, e, t) select(m, r, w, e, t) #else @@ -126,10 +128,8 @@ "max_execution_time=0\n" "max_input_time=-1\n\0"; -static char *php_optarg = NULL; -static int php_optind = 1; -static const opt_struct OPTIONS[] = { +const opt_struct OPTIONS[] = { {'a', 0, "interactive"}, {'B', 1, "process-begin"}, {'C', 0, "no-chdir"}, /* for compatibility with CGI (do not chdir to script directory) */ @@ -150,6 +150,7 @@ {'r', 1, "run"}, {'s', 0, "syntax-highlight"}, {'s', 0, "syntax-highlighting"}, + {'S', 1, "server"}, {'w', 0, "strip"}, {'?', 0, "usage"},/* help alias (both '?' and 'usage') */ {'v', 0, "version"}, @@ -172,7 +173,7 @@ static int print_module_info(zend_module_entry *module TSRMLS_DC) /* {{{ */ { @@ -3923,7 +3919,7 @@ Index: sapi/cli/php_cli.c return ZEND_HASH_APPLY_KEEP; } /* }}} */ @@ -202,7 +203,7 @@ static int print_extension_info(zend_extension *ext, void *arg TSRMLS_DC) /* {{{ */ { @@ -3932,7 +3928,7 @@ Index: sapi/cli/php_cli.c return ZEND_HASH_APPLY_KEEP; } /* }}} */ @@ -494,7 +495,7 @@ prog = "php"; } @@ -3941,7 +3937,7 @@ Index: sapi/cli/php_cli.c " %s [options] -r <code> [--] [args...]\n" " %s [options] [-B <begin_code>] -R <code> [-E <end_code>] [--] [args...]\n" " %s [options] [-B <begin_code>] -F <file> [-E <end_code>] [--] [args...]\n" @@ -650,689 +651,702 @@ } /* }}} */ @@ -4670,214 +4666,18 @@ Index: sapi/cli/php_cli.c + cli_register_file_handles(TSRMLS_C); + } - if (interactive && cli_shell_callbacks.cli_shell_run) { - exit_status = cli_shell_callbacks.cli_shell_run(TSRMLS_C); - } else { - php_execute_script(&file_handle TSRMLS_CC); - exit_status = EG(exit_status); - } + if (interactive && cli_shell_callbacks.cli_shell_run) { + exit_status = cli_shell_callbacks.cli_shell_run(TSRMLS_C); + } else { + php_execute_script(&file_handle TSRMLS_CC); + exit_status = EG(exit_status); + } + break; + case PHP_MODE_LINT: + exit_status = php_lint_script(&file_handle TSRMLS_CC); @@ -4896,7 +4696,17 @@ Index: sapi/cli/php_cli.c + case PHP_MODE_HIGHLIGHT: + { + zend_syntax_highlighter_ini syntax_highlighter_ini; - break; - case PHP_MODE_LINT: - exit_status = php_lint_script(&file_handle TSRMLS_CC); - if (exit_status==SUCCESS) { - zend_printf("No syntax errors detected in %s\n", file_handle.filename); - } else { - zend_printf("Errors parsing %s\n", file_handle.filename); - } - break; - case PHP_MODE_STRIP: if (open_file_for_scanning(&file_handle TSRMLS_CC)==SUCCESS) { - zend_strip(TSRMLS_C); + php_get_highlight_struct(&syntax_highlighter_ini); @@ -5397,7 +5207,7 @@ Index: sapi/cli/php_cli.c if (module_started) { php_module_shutdown(TSRMLS_C); } @@ -1342,12 +1356,6 @@ #endif exit(exit_status); @@ -5412,7 +5222,7 @@ Index: sapi/cli/php_cli.c Index: main/network.c =================================================================== --- main/network.c (revision 308839) +++ main/network.c (working copy) @@ -148,7 +148,7 @@ @@ -5434,19 +5244,19 @@ Index: main/network.c int n; Index: main/php_main.h =================================================================== --- main/php_main.h (revision 308839) +++ main/php_main.h (working copy) @@ -35,6 +35,7 @@ PHPAPI void php_module_shutdown_for_exec(void); PHPAPI int php_module_shutdown_wrapper(sapi_module_struct *sapi_globals); PHPAPI int php_request_startup_for_hook(TSRMLS_D); +PHPAPI void php_request_shutdown_for_hook(void *dummy); PHPAPI int php_register_extensions(zend_module_entry **ptr, int count TSRMLS_DC); Index: main/php_network.h =================================================================== --- main/php_network.h (revision 308839) +++ main/php_network.h (working copy) @@ -194,10 +194,12 @@ /* it is safe to FD_SET too many fd's under win32; the macro will simply ignore -
moriyoshi revised this gist
Mar 1, 2011 . 1 changed file with 13 additions and 1 deletion.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -1643,7 +1643,7 @@ Index: sapi/cli/php_cli_server.c =================================================================== --- sapi/cli/php_cli_server.c (revision 0) +++ sapi/cli/php_cli_server.c (revision 0) @@ -0,0 +1,2003 @@ +/* + +----------------------------------------------------------------------+ + | PHP Version 5 | @@ -2124,6 +2124,18 @@ Index: sapi/cli/php_cli_server.c + sapi_cli_server_register_variable(track_vars_array, "HTTP_HOST", buf.c TSRMLS_CC); + smart_str_free(&buf); + } + { + char **val; + if (SUCCESS == zend_hash_find(&client->request.headers, "Cookie", sizeof("Cookie"), (void**)&val)) { + sapi_cli_server_register_variable(track_vars_array, "HTTP_COOKIE", *val TSRMLS_CC); + } + } + { + char **val; + if (SUCCESS == zend_hash_find(&client->request.headers, "Referer", sizeof("Referer"), (void**)&val)) { + sapi_cli_server_register_variable(track_vars_array, "HTTP_REFERER", *val TSRMLS_CC); + } + } + sapi_cli_server_register_variable(track_vars_array, "REQUEST_URI", client->request.request_uri TSRMLS_CC); + sapi_cli_server_register_variable(track_vars_array, "REQUEST_METHOD", SG(request_info).request_method TSRMLS_CC); + sapi_cli_server_register_variable(track_vars_array, "PHP_SELF", client->request.vpath TSRMLS_CC); -
moriyoshi revised this gist
Mar 1, 2011 . 1 changed file with 38 additions and 17 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -1,3 +1,4 @@ Index: sapi/cli/config.w32 =================================================================== --- sapi/cli/config.w32 (revision 307676) +++ sapi/cli/config.w32 (working copy) @@ -1642,7 +1643,7 @@ Index: sapi/cli/php_cli_server.c =================================================================== --- sapi/cli/php_cli_server.c (revision 0) +++ sapi/cli/php_cli_server.c (revision 0) @@ -0,0 +1,1991 @@ +/* + +----------------------------------------------------------------------+ + | PHP Version 5 | @@ -1749,8 +1750,6 @@ Index: sapi/cli/php_cli_server.c + int protocol_version; + char *request_uri; + size_t request_uri_len; + char *vpath; + size_t vpath_len; + char *path_translated; @@ -1789,6 +1788,7 @@ Index: sapi/cli/php_cli_server.c +} php_cli_server_content_sender; + +typedef struct php_cli_server_client { + struct php_cli_server *server; + php_socket_t sock; + struct sockaddr *addr; + socklen_t addr_len; @@ -2114,8 +2114,18 @@ Index: sapi/cli/php_cli_server.c +static void sapi_cli_server_register_variables(zval *track_vars_array TSRMLS_DC) /* {{{ */ +{ + php_cli_server_client *client = SG(server_context); + sapi_cli_server_register_variable(track_vars_array, "DOCUMENT_ROOT", client->server->document_root TSRMLS_CC); + { + smart_str buf = { 0 }; + smart_str_appends(&buf, client->server->host); + smart_str_appendc(&buf, ':'); + smart_str_append_generic_ex(&buf, client->server->port, 0, int, _unsigned); + smart_str_0(&buf); + sapi_cli_server_register_variable(track_vars_array, "HTTP_HOST", buf.c TSRMLS_CC); + smart_str_free(&buf); + } + sapi_cli_server_register_variable(track_vars_array, "REQUEST_URI", client->request.request_uri TSRMLS_CC); + sapi_cli_server_register_variable(track_vars_array, "REQUEST_METHOD", SG(request_info).request_method TSRMLS_CC); + sapi_cli_server_register_variable(track_vars_array, "PHP_SELF", client->request.vpath TSRMLS_CC); + if (SG(request_info).path_translated) { + sapi_cli_server_register_variable(track_vars_array, "SCRIPT_FILENAME", SG(request_info).path_translated TSRMLS_CC); @@ -2171,7 +2181,7 @@ Index: sapi/cli/php_cli_server.c + + php_error, /* error handler */ + + NULL, /* header handler */ + sapi_cli_server_send_headers, /* send headers handler */ + NULL, /* send header handler */ + @@ -2560,13 +2570,11 @@ Index: sapi/cli/php_cli_server.c + return retval; +} /* }}} */ + +static int php_cli_server_request_ctor(php_cli_server_request *req) /* {{{ */ +{ + req->protocol_version = 0; + req->request_uri = NULL; + req->request_uri_len = 0; + req->vpath = NULL; + req->vpath_len = 0; + req->path_translated = NULL; @@ -2606,14 +2614,14 @@ Index: sapi/cli/php_cli_server.c + } +} /* }}} */ + +static void php_cli_server_request_translate_vpath(php_cli_server_request *request, const char *document_root, size_t document_root_len) /* {{{ */ +{ + struct stat sb; + static const char *index_files[] = { "index.html", "index.php", NULL }; + char *buf = safe_pemalloc(1, request->vpath_len, 1 + document_root_len + 1 + sizeof("index.html"), 1); + char *p = buf, *prev_patch = 0, *q, *vpath; + memmove(p, document_root, document_root_len); + p += document_root_len; + vpath = p; + if (request->vpath_len > 0 && request->vpath[0] != '/') { + *p++ = '/'; @@ -2843,7 +2851,7 @@ Index: sapi/cli/php_cli_server.c +{ + php_cli_server_client *client = parser->data; + client->request.protocol_version = parser->http_major * 100 + parser->http_minor; + php_cli_server_request_translate_vpath(&client->request, client->server->document_root, client->server->document_root_len); + { + const char *vpath = client->request.vpath, *end = vpath + client->request.vpath_len, *p = end; + client->request.ext = end; @@ -2975,8 +2983,9 @@ Index: sapi/cli/php_cli_server.c + php_cli_server_buffer_dtor(&client->capture_buffer); +} /* }}} */ + +static int php_cli_server_client_ctor(php_cli_server_client *client, php_cli_server *server, int client_sock, struct sockaddr *addr, socklen_t addr_len TSRMLS_DC) /* {{{ */ +{ + client->server = server; + client->sock = client_sock; + client->addr = addr; + client->addr_len = addr_len; @@ -2994,7 +3003,7 @@ Index: sapi/cli/php_cli_server.c + client->current_header_name_len = 0; + client->current_header_name_allocated = 0; + client->post_read_offset = 0; + if (FAILURE == php_cli_server_request_ctor(&client->request)) { + return FAILURE; + } + client->content_sender_initialized = 0; @@ -3470,7 +3479,7 @@ Index: sapi/cli/php_cli_server.c + php_cli_server_close_connection(server, client TSRMLS_CC); + } + } + return SUCCESS; +} +/* }}} */ + @@ -3525,7 +3534,7 @@ Index: sapi/cli/php_cli_server.c + closesocket(client_sock); + continue; + } + if (!(client = pemalloc(sizeof(php_cli_server_client), 1)) || FAILURE == php_cli_server_client_ctor(client, server, client_sock, sa, socklen TSRMLS_CC)) { + php_cli_server_logf("Failed to create a new request object" TSRMLS_CC); + pefree(sa, 1); + closesocket(client_sock); @@ -5411,6 +5420,18 @@ Index: main/network.c { struct sockaddr **sap; int n; Index: main/php_main.h =================================================================== --- main/php_main.h (revision 307676) +++ main/php_main.h (working copy) @@ -35,6 +35,7 @@ PHPAPI void php_module_shutdown_for_exec(void); PHPAPI int php_module_shutdown_wrapper(sapi_module_struct *sapi_globals); PHPAPI int php_request_startup_for_hook(TSRMLS_D); +PHPAPI int php_request_shutdown_for_hook(TSRMLS_D); PHPAPI int php_register_extensions(zend_module_entry **ptr, int count TSRMLS_DC); Index: main/php_network.h =================================================================== --- main/php_network.h (revision 307676) -
moriyoshi revised this gist
Mar 1, 2011 . 1 changed file with 3 additions and 4 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -1,4 +1,3 @@ =================================================================== --- sapi/cli/config.w32 (revision 307676) +++ sapi/cli/config.w32 (working copy) @@ -2627,11 +2626,11 @@ Index: sapi/cli/php_cli_server.c + if (!stat(buf, &sb)) { + if (sb.st_mode & S_IFDIR) { + const char **file = index_files; + if (p > buf && p[-1] != '/') { + *p++ = '/'; + } + while (*file) { + size_t l = strlen(*file); + memmove(p, *file, l + 1); + if (!stat(buf, &sb) && (sb.st_mode & S_IFREG)) { + p += l; -
moriyoshi revised this gist
Mar 1, 2011 . 1 changed file with 11 additions and 6 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -1643,7 +1643,7 @@ Index: sapi/cli/php_cli_server.c =================================================================== --- sapi/cli/php_cli_server.c (revision 0) +++ sapi/cli/php_cli_server.c (revision 0) @@ -0,0 +1,1983 @@ +/* + +----------------------------------------------------------------------+ + | PHP Version 5 | @@ -2629,10 +2629,12 @@ Index: sapi/cli/php_cli_server.c + const char **file = index_files; + while (*file) { + size_t l = strlen(*file); + if (p > buf && p[-1] != '/') { + *p++ = '/'; + } + memmove(p, *file, l + 1); + if (!stat(buf, &sb) && (sb.st_mode & S_IFREG)) { + p += l; + break; + } + file++; @@ -3200,7 +3202,10 @@ Index: sapi/cli/php_cli_server.c + append_essential_headers(&buffer, client, 1); + smart_str_appendl_ex(&buffer, "Content-Type: ", sizeof("Content-Type: ") - 1, 1); + smart_str_appends_ex(&buffer, mime_type, 1); + if (strncmp(mime_type, "text/", 5) == 0) { + smart_str_appends_ex(&buffer, "; charset=UTF=8", 1); + } + smart_str_appendl_ex(&buffer, "\r\n", 2, 1); + smart_str_appends_ex(&buffer, "Content-Length: ", 1); + smart_str_append_generic_ex(&buffer, client->request.sb.st_size, 1, size_t, _unsigned); + smart_str_appendl_ex(&buffer, "\r\n", 2, 1); @@ -3462,7 +3467,7 @@ Index: sapi/cli/php_cli_server.c + return FAILURE; + } + } + if (!client->content_sender.buffer.first && client->file_fd < 0) { + php_cli_server_close_connection(server, client TSRMLS_CC); + } + } -
moriyoshi revised this gist
Mar 1, 2011 . 1 changed file with 121 additions and 19 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -1643,7 +1643,7 @@ Index: sapi/cli/php_cli_server.c =================================================================== --- sapi/cli/php_cli_server.c (revision 0) +++ sapi/cli/php_cli_server.c (revision 0) @@ -0,0 +1,1978 @@ +/* + +----------------------------------------------------------------------+ + | PHP Version 5 | @@ -1734,6 +1734,7 @@ Index: sapi/cli/php_cli_server.c +#include "ext/standard/php_smart_str.h" +#include "ext/standard/html.h" +#include "ext/standard/url.h" /* for php_url_decode() */ +#include "ext/standard/php_string.h" /* for php_dirname() */ +#include "ext/standard/info.h" /* for php_info_print_style() */ +#include "php_network.h" + @@ -1817,6 +1818,8 @@ Index: sapi/cli/php_cli_server.c + int address_family; + char *document_root; + size_t document_root_len; + char *router; + size_t router_len; + socklen_t socklen; + php_cli_server_client *clients[FD_SETSIZE]; +} php_cli_server; @@ -2115,7 +2118,9 @@ Index: sapi/cli/php_cli_server.c + sapi_cli_server_register_variable(track_vars_array, "DOCUMENT_ROOT", client->request.document_root TSRMLS_CC); + sapi_cli_server_register_variable(track_vars_array, "REQUEST_URI", client->request.request_uri TSRMLS_CC); + sapi_cli_server_register_variable(track_vars_array, "PHP_SELF", client->request.vpath TSRMLS_CC); + if (SG(request_info).path_translated) { + sapi_cli_server_register_variable(track_vars_array, "SCRIPT_FILENAME", SG(request_info).path_translated TSRMLS_CC); + } + if (client->request.path_info) { + sapi_cli_server_register_variable(track_vars_array, "PATH_INFO", client->request.path_info TSRMLS_CC); + } @@ -3153,8 +3158,8 @@ Index: sapi/cli/php_cli_server.c + } + + php_request_shutdown(0); + php_cli_server_close_connection(server, client TSRMLS_CC); + destroy_request_info(&SG(request_info)); + return SUCCESS; +} /* }}} */ + @@ -3212,17 +3217,78 @@ Index: sapi/cli/php_cli_server.c +} +/* }}} */ + +static int php_cli_server_dispatch_router(php_cli_server *server, php_cli_server_client *client TSRMLS_DC) /* {{{ */ +{ + int decline = 0; + + if (!server->router) { + return 1; + } + + php_cli_server_client_populate_request_info(client, &SG(request_info)); + { + zval **val; + if (SUCCESS == zend_hash_find(&client->request.headers, "Authorization", sizeof("Authorization"), (void**)&val)) { + php_handle_auth_data(Z_STRVAL_PP(val) TSRMLS_CC); + } + } + SG(sapi_headers).http_response_code = 200; + if (FAILURE == php_request_startup(TSRMLS_C)) { + /* should never be happen */ + destroy_request_info(&SG(request_info)); + return -1; + } + { + zend_file_handle zfd; + zfd.type = ZEND_HANDLE_FILENAME; + zfd.filename = server->router; + zfd.handle.fp = NULL; + zfd.free_filename = 0; + zfd.opened_path = NULL; + zend_try { + zval *retval = NULL; + if (SUCCESS == zend_execute_scripts(ZEND_REQUIRE TSRMLS_CC, &retval, 1, &zfd)) { + if (retval) { + decline = Z_TYPE_P(retval) == IS_BOOL && !Z_LVAL_P(retval); + zval_ptr_dtor(&retval); + } + } else { + decline = 1; + } + } zend_end_try(); + } + + if (decline) { + php_request_shutdown_for_hook(0); + } else { + php_request_shutdown(0); + php_cli_server_close_connection(server, client TSRMLS_CC); + } + destroy_request_info(&SG(request_info)); + + return decline ? 1: 0; +} +/* }}} */ + +static int php_cli_server_dispatch(php_cli_server *server, php_cli_server_client *client TSRMLS_DC) /* {{{ */ +{ + int status; + + SG(server_context) = client; + status = php_cli_server_dispatch_router(server, client TSRMLS_CC); + + if (status < 0) { + goto fail; + } else if (status > 0) { + if (client->request.ext_len == 3 && memcmp(client->request.ext, "php", 3) == 0 && client->request.path_translated) { + if (SUCCESS != php_cli_server_dispatch_script(server, client TSRMLS_CC) && + SUCCESS != php_cli_server_send_error_page(server, client, 500 TSRMLS_CC)) { + goto fail; + } + } else { + if (SUCCESS != php_cli_server_begin_send_static(server, client TSRMLS_CC)) { + goto fail; + } + } + } + SG(server_context) = 0; @@ -3255,13 +3321,18 @@ Index: sapi/cli/php_cli_server.c + if (server->document_root) { + pefree(server->document_root, 1); + } + if (server->router) { + pefree(server->router, 1); + } +} /* }}} */ + +static int php_cli_server_ctor(php_cli_server *server, const char *addr, const char *document_root, const char *router TSRMLS_DC) /* {{{ */ +{ + int retval = SUCCESS; + char *host = NULL; + char *errstr = NULL; + char *_document_root = NULL; + char *_router = NULL; + int err = 0; + int port = 3000; + php_socket_t server_sock = -1; @@ -3307,15 +3378,40 @@ Index: sapi/cli/php_cli_server.c + + { + size_t document_root_len = strlen(document_root); + _document_root = pestrndup(document_root, document_root_len, 1); + if (!_document_root) { + retval = FAILURE; + goto out; + } + server->document_root = _document_root; + server->document_root_len = document_root_len; + } + + if (router) { + size_t router_len = strlen(router); + _router = pestrndup(router, router_len, 1); + if (!_router) { + retval = FAILURE; + goto out; + } + server->router = _router; + server->router_len = router_len; + } else { + server->router = NULL; + server->router_len = 0; + } + + server->is_running = 1; +out: + if (retval != SUCCESS) { + if (host) { + pefree(host, 1); + } + if (_document_root) { + pefree(_document_root, 1); + } + if (_router) { + pefree(_router, 1); + } + if (server_sock >= -1) { + closesocket(server_sock); @@ -3471,8 +3567,9 @@ Index: sapi/cli/php_cli_server.c + int c; + const char *server_bind_address = NULL; + extern const opt_struct OPTIONS[]; + char buf[MAXPATHLEN]; + const char *document_root; + const char *router = NULL; + + while ((c = php_getopt(argc, argv, OPTIONS, &php_optarg, &php_optind, 0, 2))!=-1) { + switch (c) { @@ -3486,18 +3583,23 @@ Index: sapi/cli/php_cli_server.c + struct stat sb; + document_root = argv[php_optind]; + if (stat(document_root, &sb)) { + fprintf(stderr, "Directory or script %s does not exist.\n", document_root); + return 1; + } + if ((sb.st_mode & S_IFREG)) { + strncpy(buf, document_root, sizeof(buf) - 1); + php_dirname(buf, strlen(buf)); + router = document_root; + document_root = buf; + } else if (!(sb.st_mode & S_IFDIR)) { + fprintf(stderr, "%s is neither a directory nor a script.\n", document_root); + return 1; + } + } else { + document_root = getcwd(buf, sizeof(buf)); + } + + if (FAILURE == php_cli_server_ctor(&server, server_bind_address, document_root, router TSRMLS_CC)) { + return 1; + } + sapi_module.phpinfo_as_text = 0; -
moriyoshi revised this gist
Mar 1, 2011 . 1 changed file with 415 additions and 195 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -1643,7 +1643,7 @@ Index: sapi/cli/php_cli_server.c =================================================================== --- sapi/cli/php_cli_server.c (revision 0) +++ sapi/cli/php_cli_server.c (revision 0) @@ -0,0 +1,1876 @@ +/* + +----------------------------------------------------------------------+ + | PHP Version 5 | @@ -1720,15 +1720,21 @@ Index: sapi/cli/php_cli_server.c +# define php_select(m, r, w, e, t) select(m, r, w, e, t) +# define SOCK_EINVAL EINVAL +# define SOCK_EAGAIN EAGAIN +# define SOCK_EINTR EINTR +# define SOCK_EADDRINUSE EADDRINUSE +#else +# include "win32/select.h" +# define SOCK_EINVAL WSAEINVAL +# define SOCK_EAGAIN WSAEWOULDBLOCK +# define SOCK_EINTR WSAEINTR +# define SOCK_EADDRINUSE WSAEADDRINUSE +#endif + +#include "ext/standard/file.h" /* for php_set_sock_blocking() :-( */ +#include "ext/standard/php_smart_str.h" +#include "ext/standard/html.h" +#include "ext/standard/url.h" /* for php_url_decode() */ +#include "ext/standard/info.h" /* for php_info_print_style() */ +#include "php_network.h" + +#include "php_http_parser.h" @@ -1797,6 +1803,8 @@ Index: sapi/cli/php_cli_server.c + php_cli_server_request request; + int content_sender_initialized:1; + php_cli_server_content_sender content_sender; + php_cli_server_buffer capture_buffer; + int capturing:1; + int file_fd; +} php_cli_server_client; + @@ -1867,8 +1875,8 @@ Index: sapi/cli/php_cli_server.c +}; + +static php_cli_server_http_reponse_status_code_pair template_map[] = { + { 404, "<h1 class=\"h\">%2$s</h1><p>The requested resource %3$s was not found on this server.</p>" }, + { 500, "<h1 class=\"h\">%2$s</h1><p>The server is temporality unavaiable.</p>" } +}; + +static php_cli_server_ext_mime_type_pair mime_type_map[] = { @@ -1885,6 +1893,8 @@ Index: sapi/cli/php_cli_server.c +}; + +static size_t php_cli_server_client_send_through(php_cli_server_client *client, const char *str, size_t str_len); +static php_cli_server_chunk *php_cli_server_chunk_heap_new_self_contained(size_t len); +static void php_cli_server_buffer_append(php_cli_server_buffer *buffer, php_cli_server_chunk *chunk); +static void php_cli_server_logf(const char *format TSRMLS_DC, ...); + +static void char_ptr_dtor_p(char **p) /* {{{ */ @@ -1996,7 +2006,17 @@ Index: sapi/cli/php_cli_server.c +static int sapi_cli_server_ub_write(const char *str, uint str_length TSRMLS_DC) /* {{{ */ +{ + php_cli_server_client *client = SG(server_context); + if (client->capturing) { + php_cli_server_chunk *chunk = php_cli_server_chunk_heap_new_self_contained(str_length); + if (!chunk) { + zend_bailout(); + } + memmove(chunk->data.heap.p, str, str_length); + php_cli_server_buffer_append(&client->capture_buffer, chunk); + return str_length; + } else { + return php_cli_server_client_send_through(client, str, str_length); + } +} /* }}} */ + +static void sapi_cli_server_flush(void *server_context) /* {{{ */ @@ -2026,13 +2046,12 @@ Index: sapi/cli/php_cli_server.c + sapi_header_struct *h; + zend_llist_position pos; + + if (client->capturing || SG(request_info).no_headers) { + return SAPI_HEADER_SENT_SUCCESSFULLY; + } + + if (SG(sapi_headers).http_status_line) { + smart_str_appends(&buffer, SG(sapi_headers).http_status_line); + smart_str_appendl(&buffer, "\r\n", 2); + } else { + append_http_status_line(&buffer, client->request.protocol_version, SG(sapi_headers).http_response_code, 0); @@ -2195,10 +2214,10 @@ Index: sapi/cli/php_cli_server.c + if (fd == poller->max_fd) { + while (fd > 0) { + fd--; + if (((unsigned int *)&poller->rfds)[fd / (8 * sizeof(unsigned int))] || ((unsigned int *)&poller->wfds)[fd / (8 * sizeof(unsigned int))]) { + break; + } + fd -= fd % (8 * sizeof(unsigned int)); + } + poller->max_fd = fd; + } @@ -2211,6 +2230,17 @@ Index: sapi/cli/php_cli_server.c + return php_select(poller->max_fd + 1, rfds, wfds, NULL, (struct timeval *)tv); +} /* }}} */ + +static size_t php_cli_server_chunk_size(const php_cli_server_chunk *chunk) /* {{{ */ +{ + switch (chunk->type) { + case PHP_CLI_SERVER_CHUNK_HEAP: + return chunk->data.heap.len; + case PHP_CLI_SERVER_CHUNK_IMMORTAL: + return chunk->data.immortal.len; + } + return 0; +} /* }}} */ + +static void php_cli_server_chunk_dtor(php_cli_server_chunk *chunk) /* {{{ */ +{ + switch (chunk->type) { @@ -2242,12 +2272,35 @@ Index: sapi/cli/php_cli_server.c + +static void php_cli_server_buffer_append(php_cli_server_buffer *buffer, php_cli_server_chunk *chunk) /* {{{ */ +{ + php_cli_server_chunk *last; + for (last = chunk; last->next; last = last->next); + if (!buffer->last) { + buffer->first = chunk; + } else { + buffer->last->next = chunk; + } + buffer->last = last; +} /* }}} */ + +static void php_cli_server_buffer_prepend(php_cli_server_buffer *buffer, php_cli_server_chunk *chunk) /* {{{ */ +{ + php_cli_server_chunk *last; + for (last = chunk; last->next; last = last->next); + last->next = buffer->first; + if (!buffer->last) { + buffer->last = last; + } + buffer->first = chunk; +} /* }}} */ + +static size_t php_cli_server_buffer_size(const php_cli_server_buffer *buffer) /* {{{ */ +{ + php_cli_server_chunk *chunk; + size_t retval = 0; + for (chunk = buffer->first; chunk; chunk = chunk->next) { + retval += php_cli_server_chunk_size(chunk); + } + return retval; +} /* }}} */ + +static php_cli_server_chunk *php_cli_server_chunk_immortal_new(const char *buf, size_t len) /* {{{ */ @@ -2258,6 +2311,7 @@ Index: sapi/cli/php_cli_server.c + } + + chunk->type = PHP_CLI_SERVER_CHUNK_IMMORTAL; + chunk->next = NULL; + chunk->data.immortal.p = buf; + chunk->data.immortal.len = len; + return chunk; @@ -2393,30 +2447,21 @@ Index: sapi/cli/php_cli_server.c + } +} /* }}} */ + +static int php_network_listen_socket(const char *host, int *port, int socktype, int *af, socklen_t *socklen, char **errstr TSRMLS_DC) /* {{{ */ +{ + int retval = -1; + int err = 0; + struct sockaddr *sa = NULL, **p, **sal; + + int num_addrs = php_network_getaddresses(host, socktype, &sal, errstr TSRMLS_CC); + if (num_addrs == 0) { + return -1; + } + for (p = sal; *p; p++) { + if (sa) { + pefree(sa, 1); + } + + retval = socket((*p)->sa_family, socktype, 0); + if (retval == SOCK_ERR) { + continue; @@ -2458,7 +2503,7 @@ Index: sapi/cli/php_cli_server.c + + if (bind(retval, sa, *socklen) == SOCK_CONN_ERR) { + err = php_socket_errno(); + if (err == SOCK_EINVAL || err == SOCK_EADDRINUSE) { + goto out; + } + closesocket(retval); @@ -2542,6 +2587,15 @@ Index: sapi/cli/php_cli_server.c + if (req->vpath) { + pefree(req->vpath, 1); + } + if (req->path_translated) { + pefree(req->path_translated, 1); + } + if (req->path_info) { + pefree(req->path_info, 1); + } + if (req->query_string) { + pefree(req->query_string, 1); + } + zend_hash_destroy(&req->headers); + if (req->content) { + pefree(req->content, 1); @@ -2565,14 +2619,14 @@ Index: sapi/cli/php_cli_server.c + *p = '\0'; + q = p; + while (q > buf) { + if (!stat(buf, &sb)) { + if (sb.st_mode & S_IFDIR) { + const char **file = index_files; + while (*file) { + size_t l = strlen(*file); + *p = '/'; + memmove(p + 1, *file, l + 1); + if (!stat(buf, &sb) && (sb.st_mode & S_IFREG)) { + p += l + 1; + break; + } @@ -2603,6 +2657,9 @@ Index: sapi/cli/php_cli_server.c + request->path_translated = buf; + request->path_translated_len = prev_patch - buf; + } else { + pefree(request->vpath, 1); + request->vpath = pestrndup(vpath, p - vpath, 1); + request->vpath_len = p - vpath; + request->path_translated = buf; + request->path_translated_len = p - buf; + } @@ -2611,41 +2668,70 @@ Index: sapi/cli/php_cli_server.c + +static void normalize_vpath(char **retval, size_t *retval_len, const char *vpath, size_t vpath_len, int persistent) /* {{{ */ +{ + char *decoded_vpath = NULL; + char *decoded_vpath_end; + char *p; + + *retval = NULL; + + decoded_vpath = pestrndup(vpath, vpath_len, persistent); + if (!decoded_vpath) { + return; + } + + decoded_vpath_end = decoded_vpath + php_url_decode(decoded_vpath, vpath_len); + + p = decoded_vpath; + + if (p < decoded_vpath_end && *p == '/') { + char *n = p; + while (n < decoded_vpath_end && *n == '/') n++; + memmove(++p, n, decoded_vpath_end - n); + decoded_vpath_end -= n - p; + } + + while (p < decoded_vpath_end) { + char *n = p; + while (n < decoded_vpath_end && *n != '/') n++; + if (n - p == 2 && p[0] == '.' && p[1] == '.') { + if (p > decoded_vpath) { + --p; + for (;;) { + if (p == decoded_vpath) { + if (*p == '/') { + p++; + } + break; + } + if (*(--p) == '/') { + p++; + break; + } + } + } + while (n < decoded_vpath_end && *n == '/') n++; + memmove(p, n, decoded_vpath_end - n); + decoded_vpath_end -= n - p; + } else if (n - p == 1 && p[0] == '.') { + while (n < decoded_vpath_end && *n == '/') n++; + memmove(p, n, decoded_vpath_end - n); + decoded_vpath_end -= n - p; + } else { + if (n < decoded_vpath_end) { + char *nn = n; + while (nn < decoded_vpath_end && *nn == '/') nn++; + p = n + 1; + memmove(p, nn, decoded_vpath_end - nn); + decoded_vpath_end -= nn - p; + } else { + p = n; + } + } + } + + *decoded_vpath_end = '\0'; + *retval = decoded_vpath; + *retval_len = decoded_vpath_end - decoded_vpath; +} /* }}} */ + +/* {{{ php_cli_server_client_read_request */ @@ -2869,9 +2955,18 @@ Index: sapi/cli/php_cli_server.c + +static void destroy_request_info(sapi_request_info *request_info) /* {{{ */ +{ +} /* }}} */ + +static void php_cli_server_client_begin_capture(php_cli_server_client *client) /* {{{ */ +{ + php_cli_server_buffer_ctor(&client->capture_buffer); + client->capturing = 1; +} /* }}} */ + +static void php_cli_server_client_end_capture(php_cli_server_client *client) /* {{{ */ +{ + client->capturing = 0; + php_cli_server_buffer_dtor(&client->capture_buffer); +} /* }}} */ + +static int php_cli_server_client_ctor(php_cli_server_client *client, int client_sock, struct sockaddr *addr, socklen_t addr_len, const char *document_root, size_t document_root_len TSRMLS_DC) /* {{{ */ @@ -2897,29 +2992,139 @@ Index: sapi/cli/php_cli_server.c + return FAILURE; + } + client->content_sender_initialized = 0; + client->capturing = 0; + client->file_fd = -1; + return SUCCESS; +} /* }}} */ + +static void php_cli_server_client_dtor(php_cli_server_client *client) /* {{{ */ +{ + php_cli_server_request_dtor(&client->request); + if (client->file_fd >= 0) { + close(client->file_fd); + client->file_fd = -1; + } + pefree(client->addr, 1); + pefree(client->addr_str, 1); + if (client->content_sender_initialized) { + php_cli_server_content_sender_dtor(&client->content_sender); + } + if (client->capturing) { + php_cli_server_buffer_dtor(&client->capture_buffer); + } +} /* }}} */ + +static void php_cli_server_close_connection(php_cli_server *server, php_cli_server_client *client TSRMLS_DC) /* {{{ */ +{ +#ifdef DEBUG + php_cli_server_logf("%s: Closing" TSRMLS_CC, client->addr_str); +#endif + closesocket(client->sock); + php_cli_server_poller_remove(&server->poller, POLLIN | POLLOUT, client->sock); + php_cli_server_client_dtor(client); + server->clients[client->sock] = NULL; + pefree(client, 1); +} /* }}} */ + +static int php_cli_server_send_error_page(php_cli_server *server, php_cli_server_client *client, int status TSRMLS_DC) /* {{{ */ +{ + char *escaped_request_uri = NULL; + size_t escaped_request_uri_len; + const char *status_string = get_status_string(status); + const char *content_template = get_template_string(status); + assert(status_string && content_template); + + php_cli_server_content_sender_ctor(&client->content_sender); + client->content_sender_initialized = 1; + + escaped_request_uri = php_escape_html_entities_ex((unsigned char *)client->request.request_uri, client->request.request_uri_len, &escaped_request_uri_len, 0, ENT_QUOTES, NULL, 0 TSRMLS_CC); + + { + static const char prologue_template[] = "<html><head><title>%1$d %2$s</title>"; + php_cli_server_chunk *chunk = php_cli_server_chunk_heap_new_self_contained(strlen(prologue_template) + 3 + strlen(status_string) + 1); + if (!chunk) { + goto fail; + } + sprintf(chunk->data.heap.p, prologue_template, status, status_string, escaped_request_uri); + chunk->data.heap.len = strlen(chunk->data.heap.p); + php_cli_server_buffer_append(&client->content_sender.buffer, chunk); + } + { + int err = 0; + sapi_activate_headers_only(TSRMLS_C); + php_cli_server_client_begin_capture(client); + zend_try { + php_info_print_style(TSRMLS_C); + php_cli_server_buffer_append(&client->content_sender.buffer, client->capture_buffer.first); + client->capture_buffer.first = client->capture_buffer.last = NULL; + } zend_catch { + err = 1; + } zend_end_try(); + php_cli_server_client_end_capture(client); + sapi_deactivate(TSRMLS_C); + if (err) { + goto fail; + } + } + { + static const char template[] = "</head><body>"; + php_cli_server_chunk *chunk = php_cli_server_chunk_immortal_new(template, sizeof(template) - 1); + if (!chunk) { + goto fail; + } + php_cli_server_buffer_append(&client->content_sender.buffer, chunk); + } + { + php_cli_server_chunk *chunk = php_cli_server_chunk_heap_new_self_contained(strlen(content_template) + escaped_request_uri_len + 3 + strlen(status_string) + 1); + if (!chunk) { + goto fail; + } + sprintf(chunk->data.heap.p, content_template, status, status_string, escaped_request_uri); + chunk->data.heap.len = strlen(chunk->data.heap.p); + php_cli_server_buffer_append(&client->content_sender.buffer, chunk); + } + { + static const char epilogue_template[] = "</body></html>"; + php_cli_server_chunk *chunk = php_cli_server_chunk_immortal_new(epilogue_template, sizeof(epilogue_template) - 1); + if (!chunk) { + goto fail; + } + php_cli_server_buffer_append(&client->content_sender.buffer, chunk); + } + + { + php_cli_server_chunk *chunk; + smart_str buffer = { 0 }; + append_http_status_line(&buffer, client->request.protocol_version, status, 1); + if (!buffer.c) { + /* out of memory */ + goto fail; + } + append_essential_headers(&buffer, client, 1); + smart_str_appends_ex(&buffer, "Content-Type: text/html; charset=UTF=8\r\n", 1); + smart_str_appends_ex(&buffer, "Content-Length: ", 1); + smart_str_append_generic_ex(&buffer, php_cli_server_buffer_size(&client->content_sender.buffer), 1, size_t, _unsigned); + smart_str_appendl_ex(&buffer, "\r\n", 2, 1); + smart_str_appendl_ex(&buffer, "\r\n", 2, 1); + + chunk = php_cli_server_chunk_heap_new(buffer.c, buffer.c, buffer.len); + if (!chunk) { + smart_str_free_ex(&buffer, 1); + goto fail; + } + php_cli_server_buffer_prepend(&client->content_sender.buffer, chunk); + } + + php_cli_server_logf("%s: %s - Sending error page (%d)" TSRMLS_CC, client->addr_str, client->request.request_uri, status); + php_cli_server_poller_add(&server->poller, POLLOUT, client->sock); + efree(escaped_request_uri); + return SUCCESS; + +fail: + efree(escaped_request_uri); + return FAILURE; +} /* }}} */ + +static int php_cli_server_dispatch_script(php_cli_server *server, php_cli_server_client *client TSRMLS_DC) /* {{{ */ +{ + php_cli_server_client_populate_request_info(client, &SG(request_info)); @@ -2929,7 +3134,6 @@ Index: sapi/cli/php_cli_server.c + php_handle_auth_data(Z_STRVAL_PP(val) TSRMLS_CC); + } + } + SG(sapi_headers).http_response_code = 200; + if (FAILURE == php_request_startup(TSRMLS_C)) { + /* should never be happen */ @@ -2943,7 +3147,7 @@ Index: sapi/cli/php_cli_server.c + zfd.handle.fp = NULL; + zfd.free_filename = 0; + zfd.opened_path = NULL; + zend_try { + php_execute_script(&zfd TSRMLS_CC); + } zend_end_try(); + } @@ -2954,6 +3158,105 @@ Index: sapi/cli/php_cli_server.c + return SUCCESS; +} /* }}} */ + +static int php_cli_server_begin_send_static(php_cli_server *server, php_cli_server_client *client TSRMLS_DC) /* {{{ */ +{ + int fd; + int status = 200; + + fd = client->request.path_translated ? open(client->request.path_translated, O_RDONLY): -1; + if (fd < 0) { + char *errstr = get_last_error(); + if (errstr) { + php_cli_server_logf("%s: %s - %s" TSRMLS_CC, client->addr_str, client->request.request_uri, errstr); + pefree(errstr, 1); + } else { + php_cli_server_logf("%s: %s - ?" TSRMLS_CC, client->addr_str, client->request.request_uri); + } + return php_cli_server_send_error_page(server, client, 404 TSRMLS_CC); + } + + php_cli_server_content_sender_ctor(&client->content_sender); + client->content_sender_initialized = 1; + client->file_fd = fd; + + { + php_cli_server_chunk *chunk; + smart_str buffer = { 0 }; + const char *mime_type = get_mime_type(client->request.ext, client->request.ext_len); + if (!mime_type) { + mime_type = "application/octet-stream"; + } + + append_http_status_line(&buffer, client->request.protocol_version, status, 1); + if (!buffer.c) { + /* out of memory */ + return FAILURE; + } + append_essential_headers(&buffer, client, 1); + smart_str_appendl_ex(&buffer, "Content-Type: ", sizeof("Content-Type: ") - 1, 1); + smart_str_appends_ex(&buffer, mime_type, 1); + smart_str_appends_ex(&buffer, "; charset=UTF=8\r\n", 1); + smart_str_appends_ex(&buffer, "Content-Length: ", 1); + smart_str_append_generic_ex(&buffer, client->request.sb.st_size, 1, size_t, _unsigned); + smart_str_appendl_ex(&buffer, "\r\n", 2, 1); + smart_str_appendl_ex(&buffer, "\r\n", 2, 1); + chunk = php_cli_server_chunk_heap_new(buffer.c, buffer.c, buffer.len); + if (!chunk) { + smart_str_free_ex(&buffer, 1); + return FAILURE; + } + php_cli_server_buffer_append(&client->content_sender.buffer, chunk); + } + php_cli_server_poller_add(&server->poller, POLLOUT, client->sock); + return SUCCESS; +} +/* }}} */ + +static int php_cli_server_dispatch(php_cli_server *server, php_cli_server_client *client TSRMLS_DC) /* {{{ */ +{ + SG(server_context) = client; + if (client->request.ext_len == 3 && memcmp(client->request.ext, "php", 3) == 0 && client->request.path_translated) { + if (SUCCESS != php_cli_server_dispatch_script(server, client TSRMLS_CC) && + SUCCESS != php_cli_server_send_error_page(server, client, 500 TSRMLS_CC)) { + goto fail; + } + } else { + if (SUCCESS != php_cli_server_begin_send_static(server, client TSRMLS_CC)) { + goto fail; + } + } + SG(server_context) = 0; + return SUCCESS; +fail: + SG(server_context) = 0; + php_cli_server_close_connection(server, client TSRMLS_CC); + return SUCCESS; +} + +static void php_cli_server_dtor(php_cli_server *server TSRMLS_DC) /* {{{ */ +{ + { + php_cli_server_client **p = server->clients, + **e = server->clients + sizeof(server->clients) / sizeof(*server->clients); + while (p < e) { + if (*p) { + php_cli_server_close_connection(server, *p TSRMLS_CC); + *p = NULL; + } + p++; + } + } + if (server->server_sock >= 0) { + closesocket(server->server_sock); + } + if (server->host) { + pefree(server->host, 1); + } + if (server->document_root) { + pefree(server->document_root, 1); + } +} /* }}} */ + +static int php_cli_server_ctor(php_cli_server *server, const char *addr, const char *document_root TSRMLS_DC) /* {{{ */ +{ + int retval = SUCCESS; @@ -2996,6 +3299,13 @@ Index: sapi/cli/php_cli_server.c + server->port = port; + + { + size_t i = 0; + for (i = 0; i < sizeof(server->clients) / sizeof(*server->clients); i++) { + server->clients[i] = 0; + } + } + + { + size_t document_root_len = strlen(document_root); + server->document_root = pestrndup(document_root, document_root_len, 1); + server->document_root_len = document_root_len; @@ -3014,139 +3324,19 @@ Index: sapi/cli/php_cli_server.c + return retval; +} /* }}} */ + +static int php_cli_server_recv_event_read_request(php_cli_server *server, php_cli_server_client *client TSRMLS_DC) /* {{{ */ +{ + char *errstr = NULL; + int status = php_cli_server_client_read_request(client, &errstr TSRMLS_CC); + if (status < 0) { + php_cli_server_logf("%s: Invalid request (%s)" TSRMLS_CC, client->addr_str, errstr); + efree(errstr); + php_cli_server_close_connection(server, client TSRMLS_CC); + return FAILURE; + } else if (status == 1) { + php_cli_server_logf("%s: %s" TSRMLS_CC, client->addr_str, client->request.request_uri); + php_cli_server_poller_remove(&server->poller, POLLIN, client->sock); + php_cli_server_dispatch(server, client TSRMLS_CC); + } else { + php_cli_server_poller_add(&server->poller, POLLIN, client->sock); + } @@ -3176,7 +3366,7 @@ Index: sapi/cli/php_cli_server.c + return FAILURE; + } + } + if (!client->content_sender.buffer.first) { + php_cli_server_close_connection(server, client TSRMLS_CC); + } + } @@ -3188,10 +3378,10 @@ Index: sapi/cli/php_cli_server.c +{ + php_socket_t fd = 0; + php_socket_t max_fd = server->poller.max_fd; + const unsigned int *p = (unsigned int *)fds, *e = p + (max_fd + (8 * sizeof(unsigned int)) - 1) / (8 * sizeof(unsigned int)); + unsigned int mask; + while (p < e && fd <= max_fd) { + for (mask = 1; mask; mask <<= 1, fd++) { + if (*p & mask) { + if (fd == server->server_sock) { + continue; @@ -3200,7 +3390,6 @@ Index: sapi/cli/php_cli_server.c + handler(server, server->clients[fd] TSRMLS_CC); + } + } + } + p++; + } @@ -3242,7 +3431,9 @@ Index: sapi/cli/php_cli_server.c + closesocket(client_sock); + continue; + } +#ifdef DEBUG + php_cli_server_logf("%s: Accepted" TSRMLS_CC, client->addr_str); +#endif + server->clients[client_sock] = client; + php_cli_server_recv_event_read_request(server, client TSRMLS_CC); + } @@ -3251,24 +3442,37 @@ Index: sapi/cli/php_cli_server.c + } else if (n == 0) { + /* do nothing */ + } else { + int err = php_socket_errno(); + if (err != SOCK_EINTR) { + char *errstr = php_socket_strerror(err, NULL, 0); + php_cli_server_logf("%s" TSRMLS_CC, errstr); + efree(errstr); + retval = FAILURE; + goto out; + } + } + } +out: + return retval; +} /* }}} */ + + +static php_cli_server server; + +static void php_cli_server_sigint_handler(int sig) +{ + server.is_running = 0; +}; + +int do_cli_server(int argc, char **argv TSRMLS_DC) /* {{{ */ +{ + char *php_optarg = NULL; + int php_optind = 1; + int c; + const char *server_bind_address = NULL; + extern const opt_struct OPTIONS[]; + char buf[PATH_MAX]; + const char *document_root; + + while ((c = php_getopt(argc, argv, OPTIONS, &php_optarg, &php_optind, 0, 2))!=-1) { + switch (c) { @@ -3278,16 +3482,32 @@ Index: sapi/cli/php_cli_server.c + } + } + + if (argc > php_optind) { + struct stat sb; + document_root = argv[php_optind]; + if (stat(document_root, &sb)) { + fprintf(stderr, "Directory %s does not exist.\n", document_root); + return 1; + } + if (!(sb.st_mode & S_IFDIR)) { + fprintf(stderr, "%s is not a directory.\n", document_root); + return 1; + } + } else { + document_root = getcwd(buf, sizeof(buf)); + } + + if (FAILURE == php_cli_server_ctor(&server, server_bind_address, document_root TSRMLS_CC)) { + return 1; + } + sapi_module.phpinfo_as_text = 0; + + printf("Server is listening on %s:%d... Press CTRL-C to quit.\n", server.host, server.port); + +#if defined(HAVE_SIGNAL_H) && defined(SIGINT) + signal(SIGINT, php_cli_server_sigint_handler); +#endif + php_cli_server_do_event_loop(&server TSRMLS_CC); + php_cli_server_dtor(&server TSRMLS_CC); + return 0; +} /* }}} */ -
moriyoshi revised this gist
Feb 20, 2011 . 1 changed file with 1 addition and 1 deletion.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -7,7 +7,7 @@ Index: sapi/cli/config.w32 if (PHP_CLI == "yes") { - SAPI('cli', 'php_cli.c php_cli_readline.c', 'php.exe'); + SAPI('cli', 'php_cli.c php_cli_readline.c php_http_parser.c php_cli_server.c', 'php.exe'); if (PHP_CRT_DEBUG == "yes") { ADD_FLAG("CFLAGS_CLI", "/D PHP_WIN32_DEBUG_HEAP"); } -
moriyoshi created this gist
Feb 20, 2011 .There are no files selected for viewing