root/ext/standard/head.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. PHP_FUNCTION
  2. PHP_FUNCTION
  3. php_header
  4. php_setcookie
  5. PHP_FUNCTION
  6. PHP_FUNCTION
  7. PHP_FUNCTION
  8. php_head_apply_header_list_to_hash
  9. PHP_FUNCTION
  10. PHP_FUNCTION

   1 /*
   2    +----------------------------------------------------------------------+
   3    | PHP Version 7                                                        |
   4    +----------------------------------------------------------------------+
   5    | Copyright (c) 1997-2016 The PHP Group                                |
   6    +----------------------------------------------------------------------+
   7    | This source file is subject to version 3.01 of the PHP license,      |
   8    | that is bundled with this package in the file LICENSE, and is        |
   9    | available through the world-wide-web at the following url:           |
  10    | http://www.php.net/license/3_01.txt                                  |
  11    | If you did not receive a copy of the PHP license and are unable to   |
  12    | obtain it through the world-wide-web, please send a note to          |
  13    | license@php.net so we can mail you a copy immediately.               |
  14    +----------------------------------------------------------------------+
  15    | Author: Rasmus Lerdorf <rasmus@lerdorf.on.ca>                        |
  16    +----------------------------------------------------------------------+
  17  */
  18 /* $Id$ */
  19 
  20 #include <stdio.h>
  21 #include "php.h"
  22 #include "ext/standard/php_standard.h"
  23 #include "ext/date/php_date.h"
  24 #include "SAPI.h"
  25 #include "php_main.h"
  26 #include "head.h"
  27 #ifdef TM_IN_SYS_TIME
  28 #include <sys/time.h>
  29 #else
  30 #include <time.h>
  31 #endif
  32 
  33 #include "php_globals.h"
  34 
  35 
  36 /* Implementation of the language Header() function */
  37 /* {{{ proto void header(string header [, bool replace, [int http_response_code]])
  38    Sends a raw HTTP header */
  39 PHP_FUNCTION(header)
  40 {
  41         zend_bool rep = 1;
  42         sapi_header_line ctr = {0};
  43         size_t len;
  44 
  45         if (zend_parse_parameters(ZEND_NUM_ARGS(), "s|bl", &ctr.line,
  46                                 &len, &rep, &ctr.response_code) == FAILURE)
  47                 return;
  48 
  49         ctr.line_len = (uint)len;
  50         sapi_header_op(rep ? SAPI_HEADER_REPLACE:SAPI_HEADER_ADD, &ctr);
  51 }
  52 /* }}} */
  53 
  54 /* {{{ proto void header_remove([string name])
  55    Removes an HTTP header previously set using header() */
  56 PHP_FUNCTION(header_remove)
  57 {
  58         sapi_header_line ctr = {0};
  59         size_t len = 0;
  60 
  61         if (zend_parse_parameters(ZEND_NUM_ARGS(), "|s", &ctr.line,
  62                                   &len) == FAILURE)
  63                 return;
  64 
  65         ctr.line_len = (uint)len;
  66         sapi_header_op(ZEND_NUM_ARGS() == 0 ? SAPI_HEADER_DELETE_ALL : SAPI_HEADER_DELETE, &ctr);
  67 }
  68 /* }}} */
  69 
  70 PHPAPI int php_header(void)
  71 {
  72         if (sapi_send_headers()==FAILURE || SG(request_info).headers_only) {
  73                 return 0; /* don't allow output */
  74         } else {
  75                 return 1; /* allow output */
  76         }
  77 }
  78 
  79 
  80 PHPAPI int php_setcookie(zend_string *name, zend_string *value, time_t expires, zend_string *path, zend_string *domain, int secure, int url_encode, int httponly)
  81 {
  82         char *cookie;
  83         size_t len = sizeof("Set-Cookie: ");
  84         zend_string *dt;
  85         sapi_header_line ctr = {0};
  86         int result;
  87         zend_string *encoded_value = NULL;
  88 
  89         if (!ZSTR_LEN(name)) {
  90                 zend_error( E_WARNING, "Cookie names must not be empty" );
  91                 return FAILURE;
  92         } else if (strpbrk(ZSTR_VAL(name), "=,; \t\r\n\013\014") != NULL) {   /* man isspace for \013 and \014 */
  93                 zend_error(E_WARNING, "Cookie names cannot contain any of the following '=,; \\t\\r\\n\\013\\014'" );
  94                 return FAILURE;
  95         }
  96 
  97         if (!url_encode && value &&
  98                         strpbrk(ZSTR_VAL(value), ",; \t\r\n\013\014") != NULL) { /* man isspace for \013 and \014 */
  99                 zend_error(E_WARNING, "Cookie values cannot contain any of the following ',; \\t\\r\\n\\013\\014'" );
 100                 return FAILURE;
 101         }
 102 
 103         len += ZSTR_LEN(name);
 104         if (value) {
 105                 if (url_encode) {
 106                         encoded_value = php_url_encode(ZSTR_VAL(value), ZSTR_LEN(value));
 107                         len += ZSTR_LEN(encoded_value);
 108                 } else {
 109                         encoded_value = zend_string_copy(value);
 110                         len += ZSTR_LEN(encoded_value);
 111                 }
 112         }
 113 
 114         if (path) {
 115                 len += ZSTR_LEN(path);
 116         }
 117         if (domain) {
 118                 len += ZSTR_LEN(domain);
 119         }
 120 
 121         cookie = emalloc(len + 100);
 122 
 123         if (value == NULL || ZSTR_LEN(value) == 0) {
 124                 /*
 125                  * MSIE doesn't delete a cookie when you set it to a null value
 126                  * so in order to force cookies to be deleted, even on MSIE, we
 127                  * pick an expiry date in the past
 128                  */
 129                 dt = php_format_date("D, d-M-Y H:i:s T", sizeof("D, d-M-Y H:i:s T")-1, 1, 0);
 130                 snprintf(cookie, len + 100, "Set-Cookie: %s=deleted; expires=%s; Max-Age=0", ZSTR_VAL(name), ZSTR_VAL(dt));
 131                 zend_string_free(dt);
 132         } else {
 133                 snprintf(cookie, len + 100, "Set-Cookie: %s=%s", ZSTR_VAL(name), value ? ZSTR_VAL(encoded_value) : "");
 134                 if (expires > 0) {
 135                         const char *p;
 136                         char tsdelta[13];
 137                         strlcat(cookie, COOKIE_EXPIRES, len + 100);
 138                         dt = php_format_date("D, d-M-Y H:i:s T", sizeof("D, d-M-Y H:i:s T")-1, expires, 0);
 139                         /* check to make sure that the year does not exceed 4 digits in length */
 140                         p = zend_memrchr(ZSTR_VAL(dt), '-', ZSTR_LEN(dt));
 141                         if (!p || *(p + 5) != ' ') {
 142                                 zend_string_free(dt);
 143                                 efree(cookie);
 144                                 zend_string_release(encoded_value);
 145                                 zend_error(E_WARNING, "Expiry date cannot have a year greater than 9999");
 146                                 return FAILURE;
 147                         }
 148                         strlcat(cookie, ZSTR_VAL(dt), len + 100);
 149                         zend_string_free(dt);
 150 
 151                         snprintf(tsdelta, sizeof(tsdelta), ZEND_LONG_FMT, (zend_long) difftime(expires, time(NULL)));
 152                         strlcat(cookie, COOKIE_MAX_AGE, len + 100);
 153                         strlcat(cookie, tsdelta, len + 100);
 154                 }
 155         }
 156 
 157         if (encoded_value) {
 158                 zend_string_release(encoded_value);
 159         }
 160 
 161         if (path && ZSTR_LEN(path)) {
 162                 strlcat(cookie, COOKIE_PATH, len + 100);
 163                 strlcat(cookie, ZSTR_VAL(path), len + 100);
 164         }
 165         if (domain && ZSTR_LEN(domain)) {
 166                 strlcat(cookie, COOKIE_DOMAIN, len + 100);
 167                 strlcat(cookie, ZSTR_VAL(domain), len + 100);
 168         }
 169         if (secure) {
 170                 strlcat(cookie, COOKIE_SECURE, len + 100);
 171         }
 172         if (httponly) {
 173                 strlcat(cookie, COOKIE_HTTPONLY, len + 100);
 174         }
 175 
 176         ctr.line = cookie;
 177         ctr.line_len = (uint)strlen(cookie);
 178 
 179         result = sapi_header_op(SAPI_HEADER_ADD, &ctr);
 180         efree(cookie);
 181         return result;
 182 }
 183 
 184 
 185 /* php_set_cookie(name, value, expires, path, domain, secure) */
 186 /* {{{ proto bool setcookie(string name [, string value [, int expires [, string path [, string domain [, bool secure[, bool httponly]]]]]])
 187    Send a cookie */
 188 PHP_FUNCTION(setcookie)
 189 {
 190         zend_string *name, *value = NULL, *path = NULL, *domain = NULL;
 191         zend_long expires = 0;
 192         zend_bool secure = 0, httponly = 0;
 193 
 194         if (zend_parse_parameters(ZEND_NUM_ARGS(), "S|SlSSbb",
 195                                 &name, &value, &expires, &path, &domain, &secure, &httponly) == FAILURE) {
 196                 return;
 197         }
 198 
 199         if (php_setcookie(name, value, expires, path, domain, secure, 1, httponly) == SUCCESS) {
 200                 RETVAL_TRUE;
 201         } else {
 202                 RETVAL_FALSE;
 203         }
 204 }
 205 /* }}} */
 206 
 207 /* {{{ proto bool setrawcookie(string name [, string value [, int expires [, string path [, string domain [, bool secure[, bool httponly]]]]]])
 208    Send a cookie with no url encoding of the value */
 209 PHP_FUNCTION(setrawcookie)
 210 {
 211         zend_string *name, *value = NULL, *path = NULL, *domain = NULL;
 212         zend_long expires = 0;
 213         zend_bool secure = 0, httponly = 0;
 214 
 215         if (zend_parse_parameters(ZEND_NUM_ARGS(), "S|SlSSbb",
 216                                 &name, &value, &expires, &path, &domain, &secure, &httponly) == FAILURE) {
 217                 return;
 218         }
 219 
 220         if (php_setcookie(name, value, expires, path, domain, secure, 0, httponly) == SUCCESS) {
 221                 RETVAL_TRUE;
 222         } else {
 223                 RETVAL_FALSE;
 224         }
 225 }
 226 /* }}} */
 227 
 228 
 229 /* {{{ proto bool headers_sent([string &$file [, int &$line]])
 230    Returns true if headers have already been sent, false otherwise */
 231 PHP_FUNCTION(headers_sent)
 232 {
 233         zval *arg1 = NULL, *arg2 = NULL;
 234         const char *file="";
 235         int line=0;
 236 
 237         if (zend_parse_parameters(ZEND_NUM_ARGS(), "|z/z/", &arg1, &arg2) == FAILURE)
 238                 return;
 239 
 240         if (SG(headers_sent)) {
 241                 line = php_output_get_start_lineno();
 242                 file = php_output_get_start_filename();
 243         }
 244 
 245         switch(ZEND_NUM_ARGS()) {
 246         case 2:
 247                 zval_dtor(arg2);
 248                 ZVAL_LONG(arg2, line);
 249         case 1:
 250                 zval_dtor(arg1);
 251                 if (file) {
 252                         ZVAL_STRING(arg1, file);
 253                 } else {
 254                         ZVAL_EMPTY_STRING(arg1);
 255                 }
 256                 break;
 257         }
 258 
 259         if (SG(headers_sent)) {
 260                 RETURN_TRUE;
 261         } else {
 262                 RETURN_FALSE;
 263         }
 264 }
 265 /* }}} */
 266 
 267 /* {{{ php_head_apply_header_list_to_hash
 268    Turn an llist of sapi_header_struct headers into a numerically indexed zval hash */
 269 static void php_head_apply_header_list_to_hash(void *data, void *arg)
 270 {
 271         sapi_header_struct *sapi_header = (sapi_header_struct *)data;
 272 
 273         if (arg && sapi_header) {
 274                 add_next_index_string((zval *)arg, (char *)(sapi_header->header));
 275         }
 276 }
 277 
 278 /* {{{ proto array headers_list(void)
 279    Return list of headers to be sent / already sent */
 280 PHP_FUNCTION(headers_list)
 281 {
 282         if (zend_parse_parameters_none() == FAILURE) {
 283                 return;
 284         }
 285 
 286         array_init(return_value);
 287         zend_llist_apply_with_argument(&SG(sapi_headers).headers, php_head_apply_header_list_to_hash, return_value);
 288 }
 289 /* }}} */
 290 
 291 /* {{{ proto long http_response_code([int response_code])
 292    Sets a response code, or returns the current HTTP response code */
 293 PHP_FUNCTION(http_response_code)
 294 {
 295         zend_long response_code = 0;
 296 
 297         if (zend_parse_parameters(ZEND_NUM_ARGS(), "|l", &response_code) == FAILURE) {
 298                 return;
 299         }
 300 
 301         if (response_code)
 302         {
 303                 zend_long old_response_code;
 304 
 305                 old_response_code = SG(sapi_headers).http_response_code;
 306                 SG(sapi_headers).http_response_code = (int)response_code;
 307 
 308                 if (old_response_code) {
 309                         RETURN_LONG(old_response_code);
 310                 }
 311 
 312                 RETURN_TRUE;
 313         }
 314 
 315         if (!SG(sapi_headers).http_response_code) {
 316                 RETURN_FALSE;
 317         }
 318 
 319         RETURN_LONG(SG(sapi_headers).http_response_code);
 320 }
 321 /* }}} */
 322 
 323 /*
 324  * Local variables:
 325  * tab-width: 4
 326  * c-basic-offset: 4
 327  * vim600: sw=4 ts=4 fdm=marker
 328  * vim<600: sw=4 ts=4 * End:
 329  */

/* [<][>][^][v][top][bottom][index][help] */