- adjust ini entry names to those of the globals struct
[m6w6/ext-http] / http_api.c
index e3ea4dc0499d85f097ebdf80307a5b8e8cbb7114..22542083ee1e88b3a01bbbe46909ae644f1dc281 100644 (file)
@@ -33,6 +33,11 @@ PHP_MINIT_FUNCTION(http_support)
        HTTP_LONG_CONSTANT("HTTP_SUPPORT_ENCODINGS", HTTP_SUPPORT_ENCODINGS);
        HTTP_LONG_CONSTANT("HTTP_SUPPORT_SSLREQUESTS", HTTP_SUPPORT_SSLREQUESTS);
        
+       HTTP_LONG_CONSTANT("HTTP_PARAMS_ALLOW_COMMA", HTTP_PARAMS_ALLOW_COMMA);
+       HTTP_LONG_CONSTANT("HTTP_PARAMS_ALLOW_FAILURE", HTTP_PARAMS_ALLOW_FAILURE);
+       HTTP_LONG_CONSTANT("HTTP_PARAMS_RAISE_ERROR", HTTP_PARAMS_RAISE_ERROR);
+       HTTP_LONG_CONSTANT("HTTP_PARAMS_DEFAULT", HTTP_PARAMS_DEFAULT);
+       
        return SUCCESS;
 }
 
@@ -147,13 +152,14 @@ STATUS _http_exit_ex(int status, char *header, char *body, zend_bool send_header
                return FAILURE;
        }
        
-       php_end_ob_buffers(0 TSRMLS_CC);
+       if (!OG(ob_lock)) {
+               php_end_ob_buffers(0 TSRMLS_CC);
+       }
        if ((SUCCESS == sapi_send_headers(TSRMLS_C)) && body) {
                PHPWRITE(body, strlen(body));
        }
        
-       switch (status)
-       {
+       switch (status) {
                case 301:       http_log(HTTP_G->log.redirect, "301-REDIRECT", header);                 break;
                case 302:       http_log(HTTP_G->log.redirect, "302-REDIRECT", header);                 break;
                case 303:       http_log(HTTP_G->log.redirect, "303-REDIRECT", header);                 break;
@@ -196,11 +202,13 @@ PHP_HTTP_API zval *_http_get_server_var_ex(const char *key, size_t key_size, zen
 {
        zval **hsv;
        zval **var;
-       
-       if ((SUCCESS != zend_hash_find(&EG(symbol_table), "_SERVER", sizeof("_SERVER"), (void **) &hsv)) || (Z_TYPE_PP(hsv) != IS_ARRAY)) {
+#ifdef ZEND_ENGINE_2
+       zend_is_auto_global("_SERVER", lenof("_SERVER") TSRMLS_CC);
+#endif
+       if ((SUCCESS != zend_hash_find(&EG(symbol_table), "_SERVER", sizeof("_SERVER"), (void *) &hsv)) || (Z_TYPE_PP(hsv) != IS_ARRAY)) {
                return NULL;
        }
-       if ((SUCCESS != zend_hash_find(Z_ARRVAL_PP(hsv), (char *) key, key_size, (void **) &var)) || (Z_TYPE_PP(var) != IS_STRING)) {
+       if ((SUCCESS != zend_hash_find(Z_ARRVAL_PP(hsv), (char *) key, key_size, (void *) &var)) || (Z_TYPE_PP(var) != IS_STRING)) {
                return NULL;
        }
        if (check && !(Z_STRVAL_PP(var) && Z_STRLEN_PP(var))) {
@@ -257,7 +265,7 @@ PHP_HTTP_API STATUS _http_get_request_body_ex(char **body, size_t *length, zend_
 }
 /* }}} */
 
-/* {{{ php_stream *_http_get_request_body_stream(void) */
+/* {{{ php_stream *http_get_request_body_stream(void) */
 PHP_HTTP_API php_stream *_http_get_request_body_stream(TSRMLS_D)
 {
        php_stream *s = NULL;
@@ -288,6 +296,227 @@ PHP_HTTP_API php_stream *_http_get_request_body_stream(TSRMLS_D)
 }
 /* }}} */
 
+/* {{{ void http_parse_params_default_callback(...) */
+PHP_HTTP_API void _http_parse_params_default_callback(void *arg, const char *key, int keylen, const char *val, int vallen TSRMLS_DC)
+{
+       char *kdup;
+       zval tmp, *entry;
+       HashTable *ht = (HashTable *) arg;
+       
+       if (ht) {
+               INIT_ZARR(tmp, ht);
+               
+               if (vallen) {
+                       MAKE_STD_ZVAL(entry);
+                       array_init(entry);
+                       kdup = estrndup(key, keylen);
+                       add_assoc_stringl_ex(entry, kdup, keylen + 1, (char *) val, vallen, 1);
+                       efree(kdup);
+                       add_next_index_zval(&tmp, entry);
+               } else {
+                       add_next_index_stringl(&tmp, (char *) key, keylen, 1);
+               }
+       }
+}
+/* }}} */
+
+/* {{{ STATUS http_parse_params(const char *, HashTable *) */
+PHP_HTTP_API STATUS _http_parse_params_ex(const char *param, int flags, http_parse_params_callback cb, void *cb_arg TSRMLS_DC)
+{
+#define ST_QUOTE       1
+#define ST_VALUE       2
+#define ST_KEY         3
+#define ST_ASSIGN      4
+#define ST_ADD         5
+       
+       int st = ST_KEY, keylen = 0, vallen = 0;
+       char *s, *c, *key = NULL, *val = NULL;
+       
+       for(c = s = estrdup(param);;) {
+#if 0
+               char *tk = NULL, *tv = NULL;
+               
+               if (key) {
+                       if (keylen) {
+                               tk= estrndup(key, keylen);
+                       } else {
+                               tk = ecalloc(1, 7);
+                               memcpy(tk, key, 3);
+                               tk[3]='.'; tk[4]='.'; tk[5]='.';
+                       }
+               }
+               if (val) {
+                       if (vallen) {
+                               tv = estrndup(val, vallen);
+                       } else {
+                               tv = ecalloc(1, 7);
+                               memcpy(tv, val, 3);
+                               tv[3]='.'; tv[4]='.'; tv[5]='.';
+                       }
+               }
+               fprintf(stderr, "[%6s] %c \"%s=%s\"\n",
+                               (
+                                               st == ST_QUOTE ? "QUOTE" :
+                                               st == ST_VALUE ? "VALUE" :
+                                               st == ST_KEY ? "KEY" :
+                                               st == ST_ASSIGN ? "ASSIGN" :
+                                               st == ST_ADD ? "ADD":
+                                               "HUH?"
+                               ), *c?*c:'0', tk, tv
+               );
+               STR_FREE(tk); STR_FREE(tv);
+#endif
+       continued:
+               switch (st) {
+                       case ST_QUOTE:
+                       quote:
+                               if (*c == '"') {
+                                       if (*(c-1) == '\\') {
+                                               memmove(c-1, c, strlen(c)+1);
+                                               goto quote;
+                                       } else {
+                                               goto add;
+                                       }
+                               } else {
+                                       if (!val) {
+                                               val = c;
+                                       }
+                                       if (!*c) {
+                                               --val;
+                                               st = ST_ADD;
+                                       }
+                               }
+                               break;
+                               
+                       case ST_VALUE:
+                               switch (*c) {
+                                       case '"':
+                                               if (!val) {
+                                                       st = ST_QUOTE;
+                                               }
+                                               break;
+                                       
+                                       case ' ':
+                                               break;
+                                       
+                                       case ';':
+                                       case '\0':
+                                               goto add;
+                                               break;
+                                       case ',':
+                                               if (flags & HTTP_PARAMS_ALLOW_COMMA) {
+                                                       goto add;
+                                               }
+                                       default:
+                                               if (!val) {
+                                                       val = c;
+                                               }
+                                               break;
+                               }
+                               break;
+                               
+                       case ST_KEY:
+                               switch (*c) {
+                                       case ',':
+                                               if (flags & HTTP_PARAMS_ALLOW_COMMA) {
+                                                       goto allow_comma;
+                                               }
+                                       case '\r':
+                                       case '\n':
+                                       case '\t':
+                                       case '\013':
+                                       case '\014':
+                                               goto failure;
+                                               break;
+                                       
+                                       case '=':
+                                               if (key) {
+                                                       keylen = c - key;
+                                                       st = ST_VALUE;
+                                               } else {
+                                                       goto failure;
+                                               }
+                                               break;
+                                       
+                                       case ' ':
+                                               if (key) {
+                                                       keylen = c - key;
+                                                       st = ST_ASSIGN;
+                                               }
+                                               break;
+                                       
+                                       case ';':
+                                       case '\0':
+                                       allow_comma:
+                                               if (key) {
+                                                       keylen = c-- - key;
+                                                       st = ST_ADD;
+                                               }
+                                               break;
+                                       
+                                       default:
+                                               if (!key) {
+                                                       key = c;
+                                               }
+                                               break;
+                               }
+                               break;
+                               
+                       case ST_ASSIGN:
+                               if (*c == '=') {
+                                       st = ST_VALUE;
+                               } else if (!*c || *c == ';' || ((flags & HTTP_PARAMS_ALLOW_COMMA) && *c == ',')) {
+                                       st = ST_ADD;
+                               } else if (*c != ' ') {
+                                       goto failure;
+                               }
+                               break;
+                               
+                       case ST_ADD:
+                       add:
+                               if (val) {
+                                       vallen = c - val;
+                                       if (st != ST_QUOTE) {
+                                               while (val[vallen-1] == ' ') --vallen;
+                                       }
+                               } else {
+                                       val = "";
+                                       vallen = 0;
+                               }
+                               
+                               cb(cb_arg, key, keylen, val, vallen TSRMLS_CC);
+                               
+                               st = ST_KEY;
+                               key = val = NULL;
+                               keylen = vallen = 0;
+                               break;
+               }
+               if (*c) {
+                       ++c;
+               } else if (st == ST_ADD) {
+                       goto add;
+               } else {
+                       break;
+               }
+       }
+       
+       efree(s);
+       return SUCCESS;
+       
+failure:
+       if (flags & HTTP_PARAMS_RAISE_ERROR) {
+               http_error_ex(HE_WARNING, HTTP_E_INVALID_PARAM, "Unexpected character (%c) at pos %tu of %zu", *c, c-s, strlen(s));
+       }
+       if (flags & HTTP_PARAMS_ALLOW_FAILURE) {
+               --c;
+               st = ST_ADD;
+               goto continued;
+       }
+       efree(s);
+       return FAILURE;
+}
+/* }}} */
+
 /*
  * Local variables:
  * tab-width: 4