Annotation of embedaddon/php/ext/standard/head.c, revision 1.1.1.3
1.1 misho 1: /*
2: +----------------------------------------------------------------------+
3: | PHP Version 5 |
4: +----------------------------------------------------------------------+
1.1.1.3 ! misho 5: | Copyright (c) 1997-2013 The PHP Group |
1.1 misho 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: */
1.1.1.2 misho 18: /* $Id$ */
1.1 misho 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:
44: if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|bl", &ctr.line,
45: &ctr.line_len, &rep, &ctr.response_code) == FAILURE)
46: return;
47:
48: sapi_header_op(rep ? SAPI_HEADER_REPLACE:SAPI_HEADER_ADD, &ctr TSRMLS_CC);
49: }
50: /* }}} */
51:
52: /* {{{ proto void header_remove([string name])
53: Removes an HTTP header previously set using header() */
54: PHP_FUNCTION(header_remove)
55: {
56: sapi_header_line ctr = {0};
57:
58: if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|s", &ctr.line,
59: &ctr.line_len) == FAILURE)
60: return;
61:
62: sapi_header_op(ZEND_NUM_ARGS() == 0 ? SAPI_HEADER_DELETE_ALL : SAPI_HEADER_DELETE, &ctr TSRMLS_CC);
63: }
64: /* }}} */
65:
66: PHPAPI int php_header(TSRMLS_D)
67: {
68: if (sapi_send_headers(TSRMLS_C)==FAILURE || SG(request_info).headers_only) {
69: return 0; /* don't allow output */
70: } else {
71: return 1; /* allow output */
72: }
73: }
74:
75:
76: 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, int httponly TSRMLS_DC)
77: {
78: char *cookie, *encoded_value = NULL;
79: int len=sizeof("Set-Cookie: ");
80: char *dt;
81: sapi_header_line ctr = {0};
82: int result;
83:
84: if (name && strpbrk(name, "=,; \t\r\n\013\014") != NULL) { /* man isspace for \013 and \014 */
85: zend_error( E_WARNING, "Cookie names cannot contain any of the following '=,; \\t\\r\\n\\013\\014'" );
86: return FAILURE;
87: }
88:
89: if (!url_encode && value && strpbrk(value, ",; \t\r\n\013\014") != NULL) { /* man isspace for \013 and \014 */
90: zend_error( E_WARNING, "Cookie values cannot contain any of the following ',; \\t\\r\\n\\013\\014'" );
91: return FAILURE;
92: }
93:
94: len += name_len;
95: if (value && url_encode) {
96: int encoded_value_len;
97:
98: encoded_value = php_url_encode(value, value_len, &encoded_value_len);
99: len += encoded_value_len;
100: } else if ( value ) {
101: encoded_value = estrdup(value);
102: len += value_len;
103: }
104: if (path) {
105: len += path_len;
106: }
107: if (domain) {
108: len += domain_len;
109: }
110:
111: cookie = emalloc(len + 100);
112:
113: if (value && value_len == 0) {
114: /*
115: * MSIE doesn't delete a cookie when you set it to a null value
116: * so in order to force cookies to be deleted, even on MSIE, we
117: * pick an expiry date in the past
118: */
119: dt = php_format_date("D, d-M-Y H:i:s T", sizeof("D, d-M-Y H:i:s T")-1, 1, 0 TSRMLS_CC);
120: snprintf(cookie, len + 100, "Set-Cookie: %s=deleted; expires=%s", name, dt);
121: efree(dt);
122: } else {
123: snprintf(cookie, len + 100, "Set-Cookie: %s=%s", name, value ? encoded_value : "");
124: if (expires > 0) {
1.1.1.2 misho 125: const char *p;
1.1 misho 126: strlcat(cookie, "; expires=", len + 100);
127: dt = php_format_date("D, d-M-Y H:i:s T", sizeof("D, d-M-Y H:i:s T")-1, expires, 0 TSRMLS_CC);
128: /* check to make sure that the year does not exceed 4 digits in length */
129: p = zend_memrchr(dt, '-', strlen(dt));
130: if (!p || *(p + 5) != ' ') {
131: efree(dt);
132: efree(cookie);
133: efree(encoded_value);
1.1.1.3 ! misho 134: zend_error(E_WARNING, "Expiry date cannot have a year greater than 9999");
1.1 misho 135: return FAILURE;
136: }
137: strlcat(cookie, dt, len + 100);
138: efree(dt);
139: }
140: }
141:
142: if (encoded_value) {
143: efree(encoded_value);
144: }
145:
146: if (path && path_len > 0) {
147: strlcat(cookie, "; path=", len + 100);
148: strlcat(cookie, path, len + 100);
149: }
150: if (domain && domain_len > 0) {
151: strlcat(cookie, "; domain=", len + 100);
152: strlcat(cookie, domain, len + 100);
153: }
154: if (secure) {
155: strlcat(cookie, "; secure", len + 100);
156: }
157: if (httponly) {
158: strlcat(cookie, "; httponly", len + 100);
159: }
160:
161: ctr.line = cookie;
162: ctr.line_len = strlen(cookie);
163:
164: result = sapi_header_op(SAPI_HEADER_ADD, &ctr TSRMLS_CC);
165: efree(cookie);
166: return result;
167: }
168:
169:
170: /* php_set_cookie(name, value, expires, path, domain, secure) */
171: /* {{{ proto bool setcookie(string name [, string value [, int expires [, string path [, string domain [, bool secure[, bool httponly]]]]]])
172: Send a cookie */
173: PHP_FUNCTION(setcookie)
174: {
175: char *name, *value = NULL, *path = NULL, *domain = NULL;
176: long expires = 0;
177: zend_bool secure = 0, httponly = 0;
178: int name_len, value_len = 0, path_len = 0, domain_len = 0;
179:
180: if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|slssbb", &name,
181: &name_len, &value, &value_len, &expires, &path,
182: &path_len, &domain, &domain_len, &secure, &httponly) == FAILURE) {
183: return;
184: }
185:
186: if (php_setcookie(name, name_len, value, value_len, expires, path, path_len, domain, domain_len, secure, 1, httponly TSRMLS_CC) == SUCCESS) {
187: RETVAL_TRUE;
188: } else {
189: RETVAL_FALSE;
190: }
191: }
192: /* }}} */
193:
194: /* {{{ proto bool setrawcookie(string name [, string value [, int expires [, string path [, string domain [, bool secure[, bool httponly]]]]]])
195: Send a cookie with no url encoding of the value */
196: PHP_FUNCTION(setrawcookie)
197: {
198: char *name, *value = NULL, *path = NULL, *domain = NULL;
199: long expires = 0;
200: zend_bool secure = 0, httponly = 0;
201: int name_len, value_len = 0, path_len = 0, domain_len = 0;
202:
203: if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|slssbb", &name,
204: &name_len, &value, &value_len, &expires, &path,
205: &path_len, &domain, &domain_len, &secure, &httponly) == FAILURE) {
206: return;
207: }
208:
209: if (php_setcookie(name, name_len, value, value_len, expires, path, path_len, domain, domain_len, secure, 0, httponly TSRMLS_CC) == SUCCESS) {
210: RETVAL_TRUE;
211: } else {
212: RETVAL_FALSE;
213: }
214: }
215: /* }}} */
216:
217:
218: /* {{{ proto bool headers_sent([string &$file [, int &$line]])
219: Returns true if headers have already been sent, false otherwise */
220: PHP_FUNCTION(headers_sent)
221: {
222: zval *arg1 = NULL, *arg2 = NULL;
1.1.1.2 misho 223: const char *file="";
1.1 misho 224: int line=0;
225:
226: if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|zz", &arg1, &arg2) == FAILURE)
227: return;
228:
229: if (SG(headers_sent)) {
1.1.1.2 misho 230: line = php_output_get_start_lineno(TSRMLS_C);
231: file = php_output_get_start_filename(TSRMLS_C);
1.1 misho 232: }
233:
234: switch(ZEND_NUM_ARGS()) {
235: case 2:
236: zval_dtor(arg2);
237: ZVAL_LONG(arg2, line);
238: case 1:
239: zval_dtor(arg1);
240: if (file) {
241: ZVAL_STRING(arg1, file, 1);
242: } else {
243: ZVAL_STRING(arg1, "", 1);
244: }
245: break;
246: }
247:
248: if (SG(headers_sent)) {
249: RETURN_TRUE;
250: } else {
251: RETURN_FALSE;
252: }
253: }
254: /* }}} */
255:
256: /* {{{ php_head_apply_header_list_to_hash
257: Turn an llist of sapi_header_struct headers into a numerically indexed zval hash */
258: static void php_head_apply_header_list_to_hash(void *data, void *arg TSRMLS_DC)
259: {
260: sapi_header_struct *sapi_header = (sapi_header_struct *)data;
261:
262: if (arg && sapi_header) {
263: add_next_index_string((zval *)arg, (char *)(sapi_header->header), 1);
264: }
265: }
266:
267: /* {{{ proto array headers_list(void)
268: Return list of headers to be sent / already sent */
269: PHP_FUNCTION(headers_list)
270: {
271: if (zend_parse_parameters_none() == FAILURE) {
272: return;
273: }
274:
275: if (!&SG(sapi_headers).headers) {
276: RETURN_FALSE;
277: }
278: array_init(return_value);
279: zend_llist_apply_with_argument(&SG(sapi_headers).headers, php_head_apply_header_list_to_hash, return_value TSRMLS_CC);
280: }
281: /* }}} */
282:
1.1.1.2 misho 283: /* {{{ proto long http_response_code([int response_code])
284: Sets a response code, or returns the current HTTP response code */
285: PHP_FUNCTION(http_response_code)
286: {
287: long response_code = 0;
288:
289: if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|l", &response_code) == FAILURE) {
290: return;
291: }
292:
293: if (response_code)
294: {
295: long old_response_code;
296:
297: old_response_code = SG(sapi_headers).http_response_code;
298: SG(sapi_headers).http_response_code = response_code;
299:
300: if (old_response_code) {
301: RETURN_LONG(old_response_code);
302: }
303:
304: RETURN_TRUE;
305: }
306:
307: if (!SG(sapi_headers).http_response_code) {
308: RETURN_FALSE;
309: }
310:
311: RETURN_LONG(SG(sapi_headers).http_response_code);
312: }
313: /* }}} */
314:
1.1 misho 315: /*
316: * Local variables:
317: * tab-width: 4
318: * c-basic-offset: 4
319: * vim600: sw=4 ts=4 fdm=marker
320: * vim<600: sw=4 ts=4 * End:
321: */
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>