]> granicus.if.org Git - php/commitdiff
Added apache compatible functions (apache_child_terminate, getallheaders, apache_requ...
authorDmitry Stogov <dmitry@php.net>
Fri, 27 Aug 2010 08:34:44 +0000 (08:34 +0000)
committerDmitry Stogov <dmitry@php.net>
Fri, 27 Aug 2010 08:34:44 +0000 (08:34 +0000)
NEWS
sapi/cgi/cgi_main.c
sapi/cgi/fastcgi.c
sapi/cgi/fastcgi.h

diff --git a/NEWS b/NEWS
index 6e52ca2477c00dabac375ae93f785067c2c344f6..6a5a47a2374864fa03283984f9e5abbaeb3901ec 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -4,6 +4,8 @@
 - Upgraded bundled sqlite to version 3.6.23.1. (Ilia)
 - Upgraded bundled PCRE to version 8.10. (Ilia)
 
+- Added apache compatible functions (apache_child_terminate, getallheaders,
+  apache_request_headers, apache_response_headers) to FastCGI SAPI (Dmitry)
 - Added caches to eliminate repeatable run-time bindings of functions, classes,
   constants, methods and properties (Dmitry)
 - Added a number of small performance tweaks and optimizations (Dmitry)
index b57abd3e1b2971caf1fb2d92a1d2168a6d1d3ecd..007e40ef104981ac01a43d3ad6a461f50ae594bd 100644 (file)
@@ -1444,10 +1444,205 @@ static PHP_MINFO_FUNCTION(cgi)
 }
 /* }}} */
 
+PHP_FUNCTION(apache_child_terminate) /* {{{ */
+{
+       if (ZEND_NUM_ARGS() > 0) {
+               WRONG_PARAM_COUNT;
+       }
+       if (fcgi_is_fastcgi()) {
+               fcgi_terminate();
+       }
+}
+/* }}} */
+
+static void add_request_header(char *var, unsigned int var_len, char *val, unsigned int val_len, void *arg TSRMLS_DC) /* {{{ */
+{
+       zval *return_value = (zval*)arg;
+       char *str = NULL;
+       char *p;
+       ALLOCA_FLAG(use_heap)
+
+       if (var_len > 5 &&
+           var[0] == 'H' &&
+           var[1] == 'T' &&
+           var[2] == 'T' &&
+           var[3] == 'P' &&
+           var[4] == '_') {
+
+               var_len -= 5;
+               if (var_len == 0) {
+                       return;
+               }
+               p = var + 5;
+               var = str = do_alloca(var_len + 1, use_heap);
+               *str++ = *p++;
+               while (*p) {
+                       if (*p == '_') {
+                               *str++ = '-';
+                               p++;
+                               if (*p) {
+                                       *str++ = *p++;
+                               }
+                       } else if (*p >= 'A' && *p <= 'Z') {
+                               *str++ = (*p++ - 'A' + 'a');
+                       } else {
+                               *str++ = *p++;
+                       }
+               }
+               *str = 0;
+       } else if (var_len == sizeof("CONTENT_TYPE")-1 &&
+                  memcmp(var, "CONTENT_TYPE", sizeof("CONTENT_TYPE")-1) == 0) {
+               var = "Content-Type";
+       } else if (var_len == sizeof("CONTENT_LENGTH")-1 &&
+                  memcmp(var, "CONTENT_LENGTH", sizeof("CONTENT_LENGTH")-1) == 0) {
+               var = "Content-Length";
+       } else {
+               return;
+       }
+       add_assoc_stringl_ex(return_value, var, var_len+1, val, val_len, 1);
+       if (str) {
+               free_alloca(var, use_heap);
+       }
+}
+/* }}} */
+
+PHP_FUNCTION(apache_request_headers) /* {{{ */
+{
+       if (ZEND_NUM_ARGS() > 0) {
+               WRONG_PARAM_COUNT;
+       }
+       array_init(return_value);
+       if (fcgi_is_fastcgi()) {
+               fcgi_request *request = (fcgi_request*) SG(server_context);
+
+               fcgi_loadenv(request, add_request_header, return_value TSRMLS_CC);
+       } else {
+               char buf[128];
+               char **env, *p, *q, *var, *val, *t = buf;
+               size_t alloc_size = sizeof(buf);
+               unsigned long var_len;
+
+               for (env = environ; env != NULL && *env != NULL; env++) {
+                       val = strchr(*env, '=');
+                       if (!val) {                             /* malformed entry? */
+                               continue;
+                       }
+                       var_len = val - *env;
+                       if (var_len >= alloc_size) {
+                               alloc_size = var_len + 64;
+                               t = (t == buf ? emalloc(alloc_size): erealloc(t, alloc_size));
+                       }
+                       var = *env;
+                       if (var_len > 5 &&
+                           var[0] == 'H' &&
+                           var[1] == 'T' &&
+                           var[2] == 'T' &&
+                           var[3] == 'P' &&
+                           var[4] == '_') {
+
+                               var_len -= 5;
+                               if (var_len == 0) {
+                                       continue;
+                               }
+
+                               if (var_len >= alloc_size) {
+                                       alloc_size = var_len + 64;
+                                       t = (t == buf ? emalloc(alloc_size): erealloc(t, alloc_size));
+                               }
+                               p = var + 5;
+
+                               var = q = t;
+                               *q++ = *p++;
+                               while (*p) {
+                                       if (*p == '_') {
+                                               *q++ = '-';
+                                               p++;
+                                               if (*p) {
+                                                       *q++ = *p++;
+                                               }
+                                       } else if (*p >= 'A' && *p <= 'Z') {
+                                               *q++ = (*p++ - 'A' + 'a');
+                                       } else {
+                                               *q++ = *p++;
+                                       }
+                               }
+                               *q = 0;
+                       } else if (var_len == sizeof("CONTENT_TYPE")-1 &&
+                                  memcmp(var, "CONTENT_TYPE", sizeof("CONTENT_TYPE")-1) == 0) {
+                               var = "Content-Type";
+                       } else if (var_len == sizeof("CONTENT_LENGTH")-1 &&
+                                  memcmp(var, "CONTENT_LENGTH", sizeof("CONTENT_LENGTH")-1) == 0) {
+                               var = "Content-Length";
+                       } else {
+                               continue;
+                       }
+                       val++;
+                       add_assoc_string_ex(return_value, var, var_len+1, val, 1);
+               }
+               if (t != buf && t != NULL) {
+                       efree(t);
+               }
+       }
+}
+/* }}} */
+
+static void add_response_header(sapi_header_struct *h, zval *return_value TSRMLS_DC) /* {{{ */
+{
+       char *s, *p;
+       int  len;
+       ALLOCA_FLAG(use_heap)
+
+       if (h->header_len > 0) {
+               p = strchr(h->header, ':');
+               len = p - h->header;
+               if (p && (len > 0)) {
+                       while (len > 0 && (h->header[len-1] == ' ' || h->header[len-1] == '\t')) {
+                               len--;
+                       }
+                       if (len) {
+                               s = do_alloca(len + 1, use_heap);
+                               memcpy(s, h->header, len);
+                               s[len] = 0;
+                               do {
+                                       p++;
+                               } while (*p == ' ' || *p == '\t');
+                               add_assoc_stringl_ex(return_value, s, len+1, p, h->header_len - (p - h->header), 1);
+                               free_alloca(s, use_heap);
+                       }
+               }
+       }
+}
+/* }}} */
+
+PHP_FUNCTION(apache_response_headers) /* {{{ */
+{
+       if (ZEND_NUM_ARGS() > 0) {
+               WRONG_PARAM_COUNT;
+       }
+
+       if (!&SG(sapi_headers).headers) {
+               RETURN_FALSE;
+       }
+       array_init(return_value);
+       zend_llist_apply_with_argument(&SG(sapi_headers).headers, (llist_apply_with_arg_func_t)add_response_header, return_value TSRMLS_CC);
+}
+/* }}} */
+
+ZEND_BEGIN_ARG_INFO(arginfo_no_args, 0)
+ZEND_END_ARG_INFO()
+
+const zend_function_entry cgi_functions[] = {
+       PHP_FE(apache_child_terminate, arginfo_no_args)
+       PHP_FE(apache_request_headers, arginfo_no_args)
+       PHP_FE(apache_response_headers, arginfo_no_args)
+       PHP_FALIAS(getallheaders, apache_request_headers, arginfo_no_args)
+       {NULL, NULL, NULL}
+};
+
 static zend_module_entry cgi_module_entry = {
        STANDARD_MODULE_HEADER,
        "cgi-fcgi",
-       NULL,
+       cgi_functions,
        PHP_MINIT(cgi),
        PHP_MSHUTDOWN(cgi),
        NULL,
index 8d2d7a32cb832efce698a3bc855299af644fd91b..e6632adafaf68edfeeb1e11359aef3c959df75ff 100644 (file)
@@ -396,6 +396,11 @@ int fcgi_in_shutdown(void)
        return in_shutdown;
 }
 
+void fcgi_terminate(void)
+{
+       in_shutdown = 1;
+}
+
 int fcgi_init(void)
 {
        if (!is_initialized) {
index 77277396b34f72cf95de406271889174a2ed414a..fc9c88f495861022bdb3cf1a38beb1f40744c983 100644 (file)
@@ -99,6 +99,7 @@ int fcgi_init(void);
 void fcgi_shutdown(void);
 int fcgi_is_fastcgi(void);
 int fcgi_in_shutdown(void);
+void fcgi_terminate(void);
 int fcgi_listen(const char *path, int backlog);
 fcgi_request* fcgi_init_request(int listen_socket);
 void fcgi_destroy_request(fcgi_request *req);