--- /php/php5-org/ext/standard/head.c 2005-01-07 22:30:05.000000000 +0100 +++ /php/php5-snap/ext/standard/head.c 2005-06-26 21:16:49.000000000 +0200 @@ -31,6 +31,7 @@ #include "php_globals.h" #include "safe_mode.h" +#include "string.h" /* Implementation of the language Header() function */ @@ -59,7 +60,7 @@ } -PHPAPI int php_setcookie(char *name, int name_len, char *value, int value_len, time_t expires, char *path, int path_len, char *domain, int domain_len, int secure, int url_encode TSRMLS_DC) +PHPAPI int php_setcookie(char *name, int name_len, char *value, int value_len, time_t expires, char *path, int path_len, char *domain, int domain_len, int secure, int httponly, int url_encode TSRMLS_DC) { char *cookie, *encoded_value = NULL; int len=sizeof("Set-Cookie: "); @@ -131,6 +132,9 @@ if (secure) { strcat(cookie, "; secure"); } + if (httponly) { + strcat(cookie, "; httponly"); + } ctr.line = cookie; ctr.line_len = strlen(cookie); @@ -146,18 +150,51 @@ Send a cookie */ PHP_FUNCTION(setcookie) { - char *name, *value = NULL, *path = NULL, *domain = NULL; - long expires = 0; - zend_bool secure = 0; - int name_len, value_len, path_len, domain_len; + char *name, *value = NULL, *path = NULL, *domain = NULL; + long expires = 0; + zend_bool secure = 0, httponly=0; + int name_len=0, value_len=0, path_len=0, domain_len=0; + zval*** args=NULL; + int argc=0; + + - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|slssb", &name, + argc=ZEND_NUM_ARGS(); + args = (zval ***)safe_emalloc(argc, sizeof(zval **), 0); + if (zend_get_parameters_array_ex(argc, args) == FAILURE) { //Get passed parameters from PHP + efree(args); + WRONG_PARAM_COUNT; + } + + if(argc!=3 || argc==3 && Z_TYPE_PP(args[2]) == IS_LONG) { //Decide which branch of the overloaded function is to be taken; standard branch here + efree(args); //Not needed anymore + + if (zend_parse_parameters(argc TSRMLS_CC, "s|slssb", &name, &name_len, &value, &value_len, &expires, &path, &path_len, &domain, &domain_len, &secure) == FAILURE) { return; - } + }} + else //Branch with 3rd parameter being an array is to be taken + { + zval* array; //Parameter array of setcookie + + if(Z_TYPE_PP(args[2])!=IS_ARRAY){ + php_error_docref(NULL TSRMLS_CC, E_WARNING, "3rd argument to setcookie is not an array or a long int"); + RETURN_FALSE; + } + + efree(args); //Not needed anymore + + if (zend_parse_parameters(argc TSRMLS_CC, "ssa", &name,&name_len, &value, &value_len, &array) == FAILURE) { + return; + } - if (php_setcookie(name, name_len, value, value_len, expires, path, path_len, domain, domain_len, secure, 1 TSRMLS_CC) == SUCCESS) { + if(eval_setcookie_array_param(array,&expires, &path, &path_len, &domain, &domain_len, &secure, &httponly)==FAILURE) { + return; + } + } + + if (php_setcookie(name, name_len, value, value_len, expires, path, path_len, domain, domain_len, secure, httponly, 1 TSRMLS_CC) == SUCCESS) { RETVAL_TRUE; } else { RETVAL_FALSE; @@ -169,18 +206,50 @@ Send a cookie with no url encoding of the value */ PHP_FUNCTION(setrawcookie) { - char *name, *value = NULL, *path = NULL, *domain = NULL; - long expires = 0; - zend_bool secure = 0; - int name_len, value_len, path_len, domain_len; + char *name = NULL, *value = NULL, *path = NULL, *domain = NULL; + long expires = 0; + zend_bool secure = 0, httponly=0; + int name_len=0, value_len=0, path_len=0, domain_len=0; + zval*** args=NULL; + int argc=0; + + argc=ZEND_NUM_ARGS(); + args = (zval ***)safe_emalloc(argc, sizeof(zval **), 0); + if (zend_get_parameters_array_ex(argc, args) == FAILURE) { //Get passed parameters from PHP + efree(args); + WRONG_PARAM_COUNT; + } + + if(argc!=3 || argc==3 && Z_TYPE_PP(args[2]) == IS_LONG) { //Decide which branch of the overloaded function is to be taken; standard branch here - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|slssb", &name, + efree(args); //Not needed anymore + + if (zend_parse_parameters(argc TSRMLS_CC, "s|slssb", &name, &name_len, &value, &value_len, &expires, &path, &path_len, &domain, &domain_len, &secure) == FAILURE) { return; + }} + else //Branch with 3rd parameter being an array is to be taken + { + zval* array; //Parameter array of setcookie + + if(Z_TYPE_PP(args[2])!=IS_ARRAY){ + php_error_docref(NULL TSRMLS_CC, E_WARNING, "3rd argument to setrawcookie is not an array or a long int"); + RETURN_FALSE; + } + + efree(args); //Not needed anymore + + if (zend_parse_parameters(argc TSRMLS_CC, "ssa", &name,&name_len, &value, &value_len, &array) == FAILURE) { + return; + } + + if(eval_setcookie_array_param(array,&expires, &path, &path_len, &domain, &domain_len, &secure, &httponly)==FAILURE) { + return; + } } - if (php_setcookie(name, name_len, value, value_len, expires, path, path_len, domain, domain_len, secure, 0 TSRMLS_CC) == SUCCESS) { + if (php_setcookie(name, name_len, value, value_len, expires, path, path_len, domain, domain_len, secure, httponly, 0 TSRMLS_CC) == SUCCESS) { RETVAL_TRUE; } else { RETVAL_FALSE; @@ -227,6 +296,97 @@ } /* }}} */ +/* {{{ eval_setcookie_array_param + Evaluate 3rd parameter to setcookie or setrawcookie */ +int eval_setcookie_array_param(zval *array, long *expires, char **path, int *path_len, char **domain, int *domain_len, zend_bool *secure, zend_bool *httponly) +{ + ulong index=0; //Iterator for setcookie's parameter array + zval **retval = NULL; //Iterator's values + + if(Z_TYPE_PP(&array)!=IS_ARRAY) return FAILURE; + + while(zend_hash_index_find(Z_ARRVAL_PP(&array),index,(void **) &retval)==SUCCESS && index<5){ + + switch(index) + { + case 0: + if(Z_TYPE_PP(retval)==IS_LONG){ + *expires=Z_LVAL_PP(retval); break; + } + if(Z_TYPE_PP(retval)==IS_STRING){ + if(calc_expires_from_string(retval,expires)==FAILURE) return; + } + case 1: + convert_to_string_ex(retval); + *path=Z_STRVAL_PP(retval); + *path_len=strlen(*path); break; + case 2: + convert_to_string_ex(retval); + *domain=Z_STRVAL_PP(retval); + *domain_len=strlen(*domain);break; + case 3: + convert_to_boolean_ex(retval); + *secure=Z_BVAL_PP(retval); break; + case 4: + convert_to_boolean_ex(retval); + *httponly=Z_BVAL_PP(retval); break; + + } + index++; + } + return SUCCESS; +} +/* }}} */ + +/* {{{ calc_expires_from_string + Turn a string in format Y:M:D:h:m:s into numerical value for expires */ +int calc_expires_from_string(zval **ex_string, long *expires) +{ + zval *explode_ret, *delim; //Internal explode's return values and delimiter for explode + zval **token_ret; //Tokens of exploded string Y:M:D:h:m:s + ulong index_explode=0; //Iterator for explode + char *string_content=":"; //Delelimiter to be + + + if(Z_TYPE_PP(ex_string)!=IS_STRING) return FAILURE; + + MAKE_STD_ZVAL(delim); + MAKE_STD_ZVAL(explode_ret); + ZVAL_STRING(delim,string_content,1); //Usable delimiter now + array_init(explode_ret); //Usable array now + + php_explode(delim,*ex_string,explode_ret,-1 TSRMLS_CC); //Internal explode of string Y:M:D:h:m:s + + if(Z_TYPE_PP(&explode_ret)!=IS_ARRAY){ + php_error_docref(NULL TSRMLS_CC, E_WARNING, "after internally exploding a value of type string with delimiter \":\", the result is not an array "); + return FAILURE; + } + + while(zend_hash_index_find(Z_ARRVAL_PP(&explode_ret),index_explode,(void **) &token_ret)==SUCCESS && index_explode<6){ + convert_to_long_ex(token_ret); + switch(index_explode){ + case 0: + *expires+=31536000*Z_LVAL_PP(token_ret);break; //Years (365 days) + case 1: + *expires+=2592000*Z_LVAL_PP(token_ret);break; //Months (30 days) + case 2: + *expires+=86400*Z_LVAL_PP(token_ret);break; //Days + case 3: + *expires+=3600*Z_LVAL_PP(token_ret);break; //hours + case 4: + *expires+=60*Z_LVAL_PP(token_ret);break; //minutes + case 5: + *expires+=Z_LVAL_PP(token_ret);break; //seconds + } + index_explode++; + } + *expires+=time(NULL); + *expires=abs((long) *expires); //just to be sure too large values are put in range + return SUCCESS; +} +/* }}} */ + + /* {{{ php_head_apply_header_list_to_hash Turn an llist of sapi_header_struct headers into a numerically indexed zval hash */ static void php_head_apply_header_list_to_hash(void *data, void *arg TSRMLS_DC)