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;
}
/* char *pretty_key(char *, size_t, zend_bool, zend_bool) */
char *_http_pretty_key(char *key, size_t key_len, zend_bool uctitle, zend_bool xhyphen)
{
+ size_t i;
+ int wasalpha;
+
if (key && key_len) {
- size_t i;
- int wasalpha;
- if ((wasalpha = isalpha((int) key[0]))) {
- key[0] = (char) (uctitle ? toupper((int) key[0]) : tolower((int) key[0]));
+ if ((wasalpha = HTTP_IS_CTYPE(alpha, key[0]))) {
+ key[0] = (char) (uctitle ? HTTP_TO_CTYPE(upper, key[0]) : HTTP_TO_CTYPE(lower, key[0]));
}
for (i = 1; i < key_len; i++) {
- if (isalpha((int) key[i])) {
- key[i] = (char) (((!wasalpha) && uctitle) ? toupper((int) key[i]) : tolower((int) key[i]));
+ if (HTTP_IS_CTYPE(alpha, key[i])) {
+ key[i] = (char) (((!wasalpha) && uctitle) ? HTTP_TO_CTYPE(upper, key[i]) : HTTP_TO_CTYPE(lower, key[i]));
wasalpha = 1;
} else {
if (xhyphen && (key[i] == '_')) {
#ifdef ZEND_ENGINE_2
if ((type == E_THROW) || (PG(error_handling) == EH_THROW)) {
char *message;
+ zend_class_entry *ce = http_exception_get_for_code(code);
- vspprintf(&message, 0, format, args);
- zend_throw_exception(http_exception_get_for_code(code), message, code TSRMLS_CC);
- efree(message);
+ http_try {
+ vspprintf(&message, 0, format, args);
+ zend_throw_exception(ce, message, code TSRMLS_CC);
+ efree(message);
+ } http_catch(PG(exception_class) ? PG(exception_class) : HTTP_EX_DEF_CE);
} else
#endif
php_verror(NULL, "", type, format, args TSRMLS_CC);
}
/* }}} */
+#ifdef ZEND_ENGINE_2
+static inline void copy_bt_args(zval *from, zval *to TSRMLS_DC)
+{
+ zval **args, **trace_0, *old_trace_0, *trace = NULL;
+
+ if ((trace = zend_read_property(ZEND_EXCEPTION_GET_DEFAULT(), from, "trace", lenof("trace"), 0 TSRMLS_CC))) {
+ if (Z_TYPE_P(trace) == IS_ARRAY && SUCCESS == zend_hash_index_find(Z_ARRVAL_P(trace), 0, (void *) &trace_0)) {
+ old_trace_0 = *trace_0;
+ if (Z_TYPE_PP(trace_0) == IS_ARRAY && SUCCESS == zend_hash_find(Z_ARRVAL_PP(trace_0), "args", sizeof("args"), (void *) &args)) {
+ if ((trace = zend_read_property(ZEND_EXCEPTION_GET_DEFAULT(), to, "trace", lenof("trace"), 0 TSRMLS_CC))) {
+ if (Z_TYPE_P(trace) == IS_ARRAY && SUCCESS == zend_hash_index_find(Z_ARRVAL_P(trace), 0, (void *) &trace_0)) {
+ ZVAL_ADDREF(*args);
+ add_assoc_zval(*trace_0, "args", *args);
+ }
+ }
+ }
+ }
+ }
+}
+
+/* {{{ zval *http_exception_wrap(zval *, zval *, zend_class_entry *) */
+zval *_http_exception_wrap(zval *old_exception, zval *new_exception, zend_class_entry *ce TSRMLS_DC)
+{
+ int inner = 1;
+ char *message;
+ zval *sub_exception, *tmp_exception;
+
+ if (!new_exception) {
+ MAKE_STD_ZVAL(new_exception);
+ object_init_ex(new_exception, ce);
+
+ zend_update_property(ce, new_exception, "innerException", lenof("innerException"), old_exception TSRMLS_CC);
+ copy_bt_args(old_exception, new_exception TSRMLS_CC);
+
+ sub_exception = old_exception;
+
+ while ((sub_exception = zend_read_property(Z_OBJCE_P(sub_exception), sub_exception, "innerException", lenof("innerException"), 0 TSRMLS_CC)) && Z_TYPE_P(sub_exception) == IS_OBJECT) {
+ ++inner;
+ }
+
+ spprintf(&message, 0, "Exception caused by %d inner exception(s)", inner);
+ zend_update_property_string(ZEND_EXCEPTION_GET_DEFAULT(), new_exception, "message", lenof("message"), message TSRMLS_CC);
+ efree(message);
+ } else {
+ sub_exception = new_exception;
+ tmp_exception = new_exception;
+
+ while ((tmp_exception = zend_read_property(Z_OBJCE_P(tmp_exception), tmp_exception, "innerException", lenof("innerException"), 0 TSRMLS_CC)) && Z_TYPE_P(tmp_exception) == IS_OBJECT) {
+ sub_exception = tmp_exception;
+ }
+
+ zend_update_property(Z_OBJCE_P(sub_exception), sub_exception, "innerException", lenof("innerException"), old_exception TSRMLS_CC);
+ copy_bt_args(old_exception, new_exception TSRMLS_CC);
+ copy_bt_args(old_exception, sub_exception TSRMLS_CC);
+ }
+
+ zval_ptr_dtor(&old_exception);
+ return new_exception;
+}
+/* }}} */
+#endif /* ZEND_ENGINE_2 */
+
/* {{{ void http_log(char *, char *, char *) */
void _http_log_ex(char *file, const char *ident, const char *message TSRMLS_DC)
{
struct tm nowtm;
char datetime[20] = {0};
- now = HTTP_GET_REQUEST_TIME();
+ now = HTTP_G->request.time;
strftime(datetime, sizeof(datetime), "%Y-%m-%d %H:%M:%S", php_localtime_r(&now, &nowtm));
#define HTTP_LOG_WRITE(file, type, msg) \
STATUS _http_exit_ex(int status, char *header, char *body, zend_bool send_header TSRMLS_DC)
{
if ( (send_header && (SUCCESS != http_send_status_header(status, header))) ||
- (!send_header && status && (SUCCESS != http_send_status(status)))) {
+ (status && (SUCCESS != http_send_status(status)))) {
http_error_ex(HE_WARNING, HTTP_E_HEADER, "Failed to exit with status/header: %d - %s", status, header ? header : "");
STR_FREE(header);
STR_FREE(body);
case 305: http_log(HTTP_G->log.redirect, "305-REDIRECT", header); break;
case 307: http_log(HTTP_G->log.redirect, "307-REDIRECT", header); break;
case 304: http_log(HTTP_G->log.cache, "304-CACHE", header); break;
+ case 404: http_log(HTTP_G->log.not_found, "404-NOTFOUND", NULL); break;
case 405: http_log(HTTP_G->log.allowed_methods, "405-ALLOWED", header); break;
default: http_log(NULL, header, body); break;
}
const char *found;
if ( (found = strstr(methods, method)) &&
- (found == method || !isalpha(found[-1])) &&
- (strlen(found) >= strlen(method) && !isalpha(found[strlen(method)]))) {
+ (found == method || !HTTP_IS_CTYPE(alpha, found[-1])) &&
+ (strlen(found) >= strlen(method) && !HTTP_IS_CTYPE(alpha, found[strlen(method)]))) {
return SUCCESS;
}
return FAILURE;
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))) {
return NULL;
}
- if (check && !(Z_STRVAL_PP(var) && Z_STRLEN_PP(var))) {
+ if (check && !((Z_TYPE_PP(var) == IS_STRING) && Z_STRVAL_PP(var) && Z_STRLEN_PP(var))) {
return NULL;
}
return *var;
/* }}} */
/* {{{ STATUS http_parse_params(const char *, HashTable *) */
-PHP_HTTP_API STATUS _http_parse_params_ex(const char *param, int allow_comma_sep, http_parse_params_callback cb, void *cb_arg TSRMLS_DC)
+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
st == ST_ASSIGN ? "ASSIGN" :
st == ST_ADD ? "ADD":
"HUH?"
- ), *c, tk, tv
+ ), *c?*c:'0', tk, tv
);
STR_FREE(tk); STR_FREE(tv);
#endif
+ continued:
switch (st) {
case ST_QUOTE:
quote:
case '\0':
goto add;
break;
-
+ case ',':
+ if (flags & HTTP_PARAMS_ALLOW_COMMA) {
+ goto add;
+ }
default:
if (!val) {
val = c;
case ST_KEY:
switch (*c) {
case ',':
- if (allow_comma_sep) {
+ if (flags & HTTP_PARAMS_ALLOW_COMMA) {
goto allow_comma;
}
case '\r':
case '\0':
allow_comma:
if (key) {
- keylen = c - key;
+ keylen = c-- - key;
st = ST_ADD;
}
break;
case ST_ASSIGN:
if (*c == '=') {
st = ST_VALUE;
- } else if (!*c || *c == ';') {
+ } else if (!*c || *c == ';' || ((flags & HTTP_PARAMS_ALLOW_COMMA) && *c == ',')) {
st = ST_ADD;
} else if (*c != ' ') {
goto failure;
keylen = vallen = 0;
break;
}
-
if (*c) {
++c;
} else if (st == ST_ADD) {
return SUCCESS;
failure:
- 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_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;
}