import 2.0 devl branch, suitable for PHP-trunk
[m6w6/ext-http] / php_http_cookie.c
1 /*
2 +--------------------------------------------------------------------+
3 | PECL :: http |
4 +--------------------------------------------------------------------+
5 | Redistribution and use in source and binary forms, with or without |
6 | modification, are permitted provided that the conditions mentioned |
7 | in the accompanying LICENSE file are met. |
8 +--------------------------------------------------------------------+
9 | Copyright (c) 2004-2010, Michael Wallner <mike@php.net> |
10 +--------------------------------------------------------------------+
11 */
12
13 /* $Id: http_cookie_api.c 298662 2010-04-27 13:42:32Z mike $ */
14
15 #include "php_http.h"
16
17 PHP_HTTP_API php_http_cookie_list_t *php_http_cookie_list_init(php_http_cookie_list_t *list TSRMLS_DC)
18 {
19 if (!list) {
20 list = emalloc(sizeof(*list));
21 }
22
23 zend_hash_init(&list->cookies, 0, NULL, ZVAL_PTR_DTOR, 0);
24 zend_hash_init(&list->extras, 0, NULL, ZVAL_PTR_DTOR, 0);
25
26 list->path = NULL;
27 list->domain = NULL;
28 list->expires = 0;
29 list->flags = 0;
30
31 return list;
32 }
33
34 PHP_HTTP_API php_http_cookie_list_t *php_http_cookie_list_copy(php_http_cookie_list_t *from, php_http_cookie_list_t *to TSRMLS_DC)
35 {
36 to = php_http_cookie_list_init(to TSRMLS_CC);
37
38 array_copy(&from->cookies, &to->cookies);
39 array_copy(&from->extras, &to->extras);
40
41 STR_SET(to->path, from->path ? estrdup(from->path) : NULL);
42 STR_SET(to->domain, from->domain ? estrdup(from->domain) : NULL);
43 to->expires = from->expires;
44 to->flags = from->flags;
45
46 return to;
47 }
48
49 PHP_HTTP_API void php_http_cookie_list_dtor(php_http_cookie_list_t *list TSRMLS_DC)
50 {
51 if (list) {
52 zend_hash_destroy(&list->cookies);
53 zend_hash_destroy(&list->extras);
54
55 STR_SET(list->path, NULL);
56 STR_SET(list->domain, NULL);
57 }
58 }
59
60
61
62 PHP_HTTP_API void php_http_cookie_list_free(php_http_cookie_list_t **list TSRMLS_DC)
63 {
64 if (*list) {
65 php_http_cookie_list_dtor(*list);
66 efree(*list);
67 *list = NULL;
68 }
69 }
70
71
72
73 PHP_HTTP_API const char *php_http_cookie_list_get_cookie(php_http_cookie_list_t *list, const char *name, size_t name_len TSRMLS_DC)
74 {
75 zval **cookie = NULL;
76 if ((SUCCESS != zend_hash_find(&list->cookies, name, name_len + 1, (void *) &cookie)) || (Z_TYPE_PP(cookie) != IS_STRING)) {
77 return NULL;
78 }
79 return Z_STRVAL_PP(cookie);
80 }
81
82
83
84 PHP_HTTP_API const char *php_http_cookie_list_get_extra(php_http_cookie_list_t *list, const char *name, size_t name_len TSRMLS_DC)
85 {
86 zval **extra = NULL;
87 if ((SUCCESS != zend_hash_find(&list->extras, name, name_len + 1, (void *) &extra)) || (Z_TYPE_PP(extra) != IS_STRING)) {
88 return NULL;
89 }
90 return Z_STRVAL_PP(extra);
91 }
92
93
94
95 PHP_HTTP_API void php_http_cookie_list_add_cookie(php_http_cookie_list_t *list, const char *name, size_t name_len, const char *value, size_t value_len TSRMLS_DC)
96 {
97 zval *cookie_value;
98 char *key = estrndup(name, name_len);
99 MAKE_STD_ZVAL(cookie_value);
100 ZVAL_STRINGL(cookie_value, estrndup(value, value_len), value_len, 0);
101 zend_hash_update(&list->cookies, key, name_len + 1, (void *) &cookie_value, sizeof(zval *), NULL);
102 efree(key);
103 }
104
105
106
107 PHP_HTTP_API void php_http_cookie_list_add_extra(php_http_cookie_list_t *list, const char *name, size_t name_len, const char *value, size_t value_len TSRMLS_DC)
108 {
109 zval *cookie_value;
110 char *key = estrndup(name, name_len);
111 MAKE_STD_ZVAL(cookie_value);
112 ZVAL_STRINGL(cookie_value, estrndup(value, value_len), value_len, 0);
113 zend_hash_update(&list->extras, key, name_len + 1, (void *) &cookie_value, sizeof(zval *), NULL);
114 efree(key);
115 }
116
117
118 typedef struct php_http_param_parse_cb_arg {
119 php_http_cookie_list_t *list;
120 long flags;
121 char **allowed_extras;
122 } php_http_parse_param_cb_arg_t;
123
124
125 static void php_http_cookie_parse_callback(void *ptr, const char *key, int keylen, const char *val, int vallen TSRMLS_DC)
126 {
127 php_http_parse_param_cb_arg_t *arg = (php_http_parse_param_cb_arg_t *) ptr;
128
129 #define _KEY_IS(s) (keylen == lenof(s) && !strncasecmp(key, (s), keylen))
130 if _KEY_IS("path") {
131 STR_SET(arg->list->path, estrndup(val, vallen));
132 } else if _KEY_IS("domain") {
133 STR_SET(arg->list->domain, estrndup(val, vallen));
134 } else if _KEY_IS("expires") {
135 char *date = estrndup(val, vallen);
136 arg->list->expires = php_parse_date(date, NULL TSRMLS_CC);
137 efree(date);
138 } else if _KEY_IS("secure") {
139 arg->list->flags |= PHP_HTTP_COOKIE_SECURE;
140 } else if _KEY_IS("httpOnly") {
141 arg->list->flags |= PHP_HTTP_COOKIE_HTTPONLY;
142 } else {
143 /* check for extra */
144 if (arg->allowed_extras) {
145 char **ae = arg->allowed_extras;
146
147 for (; *ae; ++ae) {
148 if ((size_t) keylen == strlen(*ae) && !strncasecmp(key, *ae, keylen)) {
149 if (arg->flags & PHP_HTTP_COOKIE_PARSE_RAW) {
150 php_http_cookie_list_add_extra(arg->list, key, keylen, val, vallen TSRMLS_CC);
151 } else {
152 char *dec = estrndup(val, vallen);
153 int declen = php_url_decode(dec, vallen);
154
155 php_http_cookie_list_add_extra(arg->list, key, keylen, dec, declen TSRMLS_CC);
156 efree(dec);
157 }
158 return;
159 }
160 }
161 }
162 /* new cookie */
163 if (arg->flags & PHP_HTTP_COOKIE_PARSE_RAW) {
164 php_http_cookie_list_add_cookie(arg->list, key, keylen, val, vallen TSRMLS_CC);
165 } else {
166 char *dec = estrndup(val, vallen);
167 int declen = php_url_decode(dec, vallen);
168
169 php_http_cookie_list_add_cookie(arg->list, key, keylen, dec, declen TSRMLS_CC);
170 efree(dec);
171 }
172 }
173 }
174
175
176
177 PHP_HTTP_API php_http_cookie_list_t *php_http_cookie_list_parse(php_http_cookie_list_t *list, const char *string, long flags, char **allowed_extras TSRMLS_DC)
178 {
179 int free_list = !list;
180 php_http_parse_param_cb_arg_t arg;
181
182 list = php_http_cookie_list_init(list TSRMLS_CC);
183
184 arg.list = list;
185 arg.flags = flags;
186 arg.allowed_extras = allowed_extras;
187
188 if (SUCCESS != php_http_params_parse(string, PHP_HTTP_PARAMS_RAISE_ERROR, php_http_cookie_parse_callback, &arg TSRMLS_CC)) {
189 if (free_list) {
190 php_http_cookie_list_free(&list TSRMLS_CC);
191 } else {
192 php_http_cookie_list_dtor(list TSRMLS_CC);
193 }
194 list = NULL;
195 }
196
197 return list;
198 }
199
200
201
202 PHP_HTTP_API void php_http_cookie_list_to_struct(php_http_cookie_list_t *list, zval *strct TSRMLS_DC)
203 {
204 zval array, *cookies, *extras;
205
206 INIT_PZVAL_ARRAY(&array, HASH_OF(strct));
207
208 MAKE_STD_ZVAL(cookies);
209 array_init(cookies);
210 zend_hash_copy(Z_ARRVAL_P(cookies), &list->cookies, (copy_ctor_func_t) zval_add_ref, NULL, sizeof(zval *));
211 add_assoc_zval(&array, "cookies", cookies);
212
213 MAKE_STD_ZVAL(extras);
214 array_init(extras);
215 zend_hash_copy(Z_ARRVAL_P(extras), &list->extras, (copy_ctor_func_t) zval_add_ref, NULL, sizeof(zval *));
216 add_assoc_zval(&array, "extras", extras);
217
218 add_assoc_long(&array, "flags", list->flags);
219 add_assoc_long(&array, "expires", (long) list->expires);
220 add_assoc_string(&array, "path", STR_PTR(list->path), 1);
221 add_assoc_string(&array, "domain", STR_PTR(list->domain), 1);
222 }
223
224
225
226 PHP_HTTP_API php_http_cookie_list_t *php_http_cookie_list_from_struct(php_http_cookie_list_t *list, zval *strct TSRMLS_DC)
227 {
228 zval **tmp, *cpy;
229 HashTable *ht = HASH_OF(strct);
230
231 list = php_http_cookie_list_init(list TSRMLS_CC);
232
233 if (SUCCESS == zend_hash_find(ht, "cookies", sizeof("cookies"), (void *) &tmp) && Z_TYPE_PP(tmp) == IS_ARRAY) {
234 zend_hash_copy(&list->cookies, Z_ARRVAL_PP(tmp), (copy_ctor_func_t) zval_add_ref, NULL, sizeof(zval *));
235 }
236 if (SUCCESS == zend_hash_find(ht, "extras", sizeof("extras"), (void *) &tmp) && Z_TYPE_PP(tmp) == IS_ARRAY) {
237 zend_hash_copy(&list->extras, Z_ARRVAL_PP(tmp), (copy_ctor_func_t) zval_add_ref, NULL, sizeof(zval *));
238 }
239 if (SUCCESS == zend_hash_find(ht, "flags", sizeof("flags"), (void *) &tmp)) {
240 switch (Z_TYPE_PP(tmp)) {
241 case IS_LONG:
242 list->flags = Z_LVAL_PP(tmp);
243 break;
244 case IS_DOUBLE:
245 list->flags = (long) Z_DVAL_PP(tmp);
246 break;
247 case IS_STRING:
248 cpy = php_http_zsep(IS_LONG, *tmp);
249 list->flags = Z_LVAL_P(cpy);
250 zval_ptr_dtor(&cpy);
251 break;
252 default:
253 break;
254 }
255 }
256 if (SUCCESS == zend_hash_find(ht, "expires", sizeof("expires"), (void *) &tmp)) {
257 switch (Z_TYPE_PP(tmp)) {
258 case IS_LONG:
259 list->expires = Z_LVAL_PP(tmp);
260 break;
261 case IS_DOUBLE:
262 list->expires = (long) Z_DVAL_PP(tmp);
263 break;
264 case IS_STRING:
265 cpy = php_http_zsep(IS_LONG, *tmp);
266 if (Z_LVAL_P(cpy)) {
267 list->expires = Z_LVAL_P(cpy);
268 } else {
269 time_t expires = php_parse_date(Z_STRVAL_PP(tmp), NULL TSRMLS_CC);
270 if (expires > 0) {
271 list->expires = expires;
272 }
273 }
274 zval_ptr_dtor(&cpy);
275 break;
276 default:
277 break;
278 }
279 }
280 if (SUCCESS == zend_hash_find(ht, "path", sizeof("path"), (void *) &tmp) && Z_TYPE_PP(tmp) == IS_STRING) {
281 list->path = estrndup(Z_STRVAL_PP(tmp), Z_STRLEN_PP(tmp));
282 }
283 if (SUCCESS == zend_hash_find(ht, "domain", sizeof("domain"), (void *) &tmp) && Z_TYPE_PP(tmp) == IS_STRING) {
284 list->domain = estrndup(Z_STRVAL_PP(tmp), Z_STRLEN_PP(tmp));
285 }
286
287 return list;
288 }
289
290
291
292 static inline void append_encoded(php_http_buffer *buf, const char *key, size_t key_len, const char *val, size_t val_len)
293 {
294 char *enc_str[2];
295 int enc_len[2];
296
297 enc_str[0] = php_url_encode(key, key_len, &enc_len[0]);
298 enc_str[1] = php_url_encode(val, val_len, &enc_len[1]);
299
300 php_http_buffer_append(buf, enc_str[0], enc_len[0]);
301 php_http_buffer_appends(buf, "=");
302 php_http_buffer_append(buf, enc_str[1], enc_len[1]);
303 php_http_buffer_appends(buf, "; ");
304
305 efree(enc_str[0]);
306 efree(enc_str[1]);
307 }
308
309
310
311 PHP_HTTP_API void php_http_cookie_list_to_string(php_http_cookie_list_t *list, char **str, size_t *len TSRMLS_DC)
312 {
313 php_http_buffer buf;
314 zval **val;
315 php_http_array_hashkey_t key = php_http_array_hashkey_init(0);
316 HashPosition pos;
317
318 php_http_buffer_init(&buf);
319
320 FOREACH_HASH_KEYVAL(pos, &list->cookies, key, val) {
321 if (key.type == HASH_KEY_IS_STRING && key.len) {
322 zval *tmp = php_http_zsep(IS_STRING, *val);
323 append_encoded(&buf, key.str, key.len-1, Z_STRVAL_P(tmp), Z_STRLEN_P(tmp));
324 zval_ptr_dtor(&tmp);
325 }
326 }
327
328 if (list->domain && *list->domain) {
329 php_http_buffer_appendf(&buf, "domain=%s; ", list->domain);
330 }
331 if (list->path && *list->path) {
332 php_http_buffer_appendf(&buf, "path=%s; ", list->path);
333 }
334 if (list->expires) {
335 char *date = php_format_date(ZEND_STRL(PHP_HTTP_DATE_FORMAT), list->expires, 0 TSRMLS_CC);
336 php_http_buffer_appendf(&buf, "expires=%s; ", date);
337 efree(date);
338 }
339
340 FOREACH_HASH_KEYVAL(pos, &list->extras, key, val) {
341 if (key.type == HASH_KEY_IS_STRING && key.len) {
342 zval *tmp = php_http_zsep(IS_STRING, *val);
343 append_encoded(&buf, key.str, key.len-1, Z_STRVAL_P(tmp), Z_STRLEN_P(tmp));
344 }
345 }
346
347 if (list->flags & PHP_HTTP_COOKIE_SECURE) {
348 php_http_buffer_appends(&buf, "secure; ");
349 }
350 if (list->flags & PHP_HTTP_COOKIE_HTTPONLY) {
351 php_http_buffer_appends(&buf, "httpOnly; ");
352 }
353
354 php_http_buffer_fix(&buf);
355 *str = PHP_HTTP_BUFFER_VAL(&buf);
356 *len = PHP_HTTP_BUFFER_LEN(&buf);
357 }
358
359 #define PHP_HTTP_BEGIN_ARGS(method, req_args) PHP_HTTP_BEGIN_ARGS_EX(HttpCookie, method, 0, req_args)
360 #define PHP_HTTP_EMPTY_ARGS(method) PHP_HTTP_EMPTY_ARGS_EX(HttpCookie, method, 0)
361 #define PHP_HTTP_COOKIE_ME(method, visibility) PHP_ME(HttpCookie, method, PHP_HTTP_ARGS(HttpCookie, method), visibility)
362
363 PHP_HTTP_BEGIN_ARGS(__construct, 0)
364 PHP_HTTP_ARG_VAL(cookie_string, 0)
365 PHP_HTTP_ARG_VAL(parser_flags, 0)
366 PHP_HTTP_ARG_VAL(allowed_extras, 0)
367 PHP_HTTP_END_ARGS;
368
369 PHP_HTTP_EMPTY_ARGS(toArray);
370 PHP_HTTP_EMPTY_ARGS(getCookies);
371 PHP_HTTP_EMPTY_ARGS(getExtras);
372 PHP_HTTP_EMPTY_ARGS(getDomain);
373 PHP_HTTP_EMPTY_ARGS(getPath);
374 PHP_HTTP_EMPTY_ARGS(getExpires);
375 PHP_HTTP_EMPTY_ARGS(getFlags);
376 PHP_HTTP_EMPTY_ARGS(toString);
377
378 PHP_HTTP_BEGIN_ARGS(setDomain, 0)
379 PHP_HTTP_ARG_VAL(value, 0)
380 PHP_HTTP_END_ARGS;
381 PHP_HTTP_BEGIN_ARGS(setPath, 0)
382 PHP_HTTP_ARG_VAL(value, 0)
383 PHP_HTTP_END_ARGS;
384 PHP_HTTP_BEGIN_ARGS(setExpires, 0)
385 PHP_HTTP_ARG_VAL(value, 0)
386 PHP_HTTP_END_ARGS;
387 PHP_HTTP_BEGIN_ARGS(setFlags, 0)
388 PHP_HTTP_ARG_VAL(value, 0)
389 PHP_HTTP_END_ARGS;
390
391 PHP_HTTP_BEGIN_ARGS(setCookies, 0)
392 PHP_HTTP_ARG_VAL(cookies, 0)
393 PHP_HTTP_END_ARGS;
394 PHP_HTTP_BEGIN_ARGS(addCookies, 1)
395 PHP_HTTP_ARG_VAL(cookies, 0)
396 PHP_HTTP_END_ARGS;
397 PHP_HTTP_BEGIN_ARGS(setExtras, 0)
398 PHP_HTTP_ARG_VAL(extras, 0)
399 PHP_HTTP_END_ARGS;
400 PHP_HTTP_BEGIN_ARGS(addExtras, 1)
401 PHP_HTTP_ARG_VAL(extras, 0)
402 PHP_HTTP_END_ARGS;
403 PHP_HTTP_BEGIN_ARGS(setCookie, 1)
404 PHP_HTTP_ARG_VAL(cookie_name, 0)
405 PHP_HTTP_ARG_VAL(cookie_value, 0)
406 PHP_HTTP_END_ARGS;
407 PHP_HTTP_BEGIN_ARGS(addCookie, 1)
408 PHP_HTTP_ARG_VAL(cookie_name, 0)
409 PHP_HTTP_ARG_VAL(cookie_value, 0)
410 PHP_HTTP_END_ARGS;
411 PHP_HTTP_BEGIN_ARGS(getCookie, 1)
412 PHP_HTTP_ARG_VAL(name, 0)
413 PHP_HTTP_END_ARGS;
414 PHP_HTTP_BEGIN_ARGS(setExtra, 1)
415 PHP_HTTP_ARG_VAL(extra_name, 0)
416 PHP_HTTP_ARG_VAL(extra_value, 0)
417 PHP_HTTP_END_ARGS;
418 PHP_HTTP_BEGIN_ARGS(addExtra, 1)
419 PHP_HTTP_ARG_VAL(extra_name, 0)
420 PHP_HTTP_ARG_VAL(extra_value, 0)
421 PHP_HTTP_END_ARGS;
422 PHP_HTTP_BEGIN_ARGS(getExtra, 1)
423 PHP_HTTP_ARG_VAL(name, 0)
424 PHP_HTTP_END_ARGS;
425
426 zend_class_entry *php_http_cookie_class_entry;
427 zend_function_entry php_http_cookie_method_entry[] = {
428 PHP_HTTP_COOKIE_ME(__construct, ZEND_ACC_PUBLIC)
429 PHP_HTTP_COOKIE_ME(getCookies, ZEND_ACC_PUBLIC)
430 PHP_HTTP_COOKIE_ME(setCookies, ZEND_ACC_PUBLIC)
431 PHP_HTTP_COOKIE_ME(addCookies, ZEND_ACC_PUBLIC)
432 PHP_HTTP_COOKIE_ME(getCookie, ZEND_ACC_PUBLIC)
433 PHP_HTTP_COOKIE_ME(setCookie, ZEND_ACC_PUBLIC)
434 PHP_HTTP_COOKIE_ME(addCookie, ZEND_ACC_PUBLIC)
435
436 PHP_HTTP_COOKIE_ME(getExtras, ZEND_ACC_PUBLIC)
437 PHP_HTTP_COOKIE_ME(setExtras, ZEND_ACC_PUBLIC)
438 PHP_HTTP_COOKIE_ME(addExtras, ZEND_ACC_PUBLIC)
439 PHP_HTTP_COOKIE_ME(getExtra, ZEND_ACC_PUBLIC)
440 PHP_HTTP_COOKIE_ME(setExtra, ZEND_ACC_PUBLIC)
441 PHP_HTTP_COOKIE_ME(addExtra, ZEND_ACC_PUBLIC)
442
443 PHP_HTTP_COOKIE_ME(getDomain, ZEND_ACC_PUBLIC)
444 PHP_HTTP_COOKIE_ME(setDomain, ZEND_ACC_PUBLIC)
445 PHP_HTTP_COOKIE_ME(getPath, ZEND_ACC_PUBLIC)
446 PHP_HTTP_COOKIE_ME(setPath, ZEND_ACC_PUBLIC)
447 PHP_HTTP_COOKIE_ME(getExpires, ZEND_ACC_PUBLIC)
448 PHP_HTTP_COOKIE_ME(setExpires, ZEND_ACC_PUBLIC)
449 PHP_HTTP_COOKIE_ME(getFlags, ZEND_ACC_PUBLIC)
450 PHP_HTTP_COOKIE_ME(setFlags, ZEND_ACC_PUBLIC)
451
452 PHP_HTTP_COOKIE_ME(toArray, ZEND_ACC_PUBLIC)
453 PHP_HTTP_COOKIE_ME(toString, ZEND_ACC_PUBLIC)
454 ZEND_MALIAS(HttpCookie, __toString, toString, PHP_HTTP_ARGS(HttpCookie, toString), ZEND_ACC_PUBLIC)
455
456 EMPTY_FUNCTION_ENTRY
457 };
458 static zend_object_handlers php_http_cookie_object_handlers;
459
460 zend_object_value php_http_cookie_object_new(zend_class_entry *ce TSRMLS_DC)
461 {
462 return php_http_cookie_object_new_ex(ce, NULL, NULL TSRMLS_CC);
463 }
464
465 zend_object_value php_http_cookie_object_new_ex(zend_class_entry *ce, php_http_cookie_list_t *list, php_http_cookie_object_t **ptr TSRMLS_DC)
466 {
467 zend_object_value ov;
468 php_http_cookie_object_t *o;
469
470 o = ecalloc(sizeof(*o), 1);
471 zend_object_std_init((zend_object *) o, ce TSRMLS_CC);
472 object_properties_init((zend_object *) o, ce);
473
474 if (list) {
475 o->list = list;
476 }
477
478 if (ptr) {
479 *ptr = o;
480 }
481
482 ov.handle = zend_objects_store_put(o, NULL, php_http_cookie_object_free, NULL TSRMLS_CC);
483 ov.handlers = &php_http_cookie_object_handlers;
484
485 return ov;
486 }
487
488 zend_object_value php_http_cookie_object_clone(zval *this_ptr TSRMLS_CC)
489 {
490 php_http_cookie_object_t *new_obj, *old_obj = zend_object_store_get_object(getThis() TSRMLS_CC);
491 zend_object_value ov;
492
493 ov = php_http_cookie_object_new_ex(old_obj->o.ce, php_http_cookie_list_copy(old_obj->list, NULL TSRMLS_CC), &new_obj TSRMLS_CC);
494 zend_objects_clone_members((zend_object *) new_obj, ov, (zend_object *) old_obj, Z_OBJ_HANDLE_P(getThis()) TSRMLS_CC);
495
496 return ov;
497 }
498
499 void php_http_cookie_object_free(void *object TSRMLS_CC)
500 {
501 php_http_cookie_object_t *obj = object;
502
503 php_http_cookie_list_free(&obj->list TSRMLS_CC);
504 zend_object_std_dtor((zend_object *) obj TSRMLS_CC);
505 efree(obj);
506 }
507
508 PHP_METHOD(HttpCookie, __construct)
509 {
510 with_error_handling(EH_THROW, PHP_HTTP_EX_CE(runtime)) {
511 zval *zcookie = NULL;
512 long flags = 0;
513 HashTable *allowed_extras = NULL;
514
515 if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|z!lH", &zcookie, &flags, &allowed_extras)) {
516 if (zcookie) {
517 with_error_handling(EH_THROW, PHP_HTTP_EX_CE(cookie)) {
518 char **ae = NULL;
519 php_http_cookie_object_t *obj = zend_object_store_get_object(getThis() TSRMLS_CC);
520
521 if (allowed_extras && zend_hash_num_elements(allowed_extras)) {
522 char **ae_ptr = safe_emalloc(zend_hash_num_elements(allowed_extras) + 1, sizeof(char *), 0);
523 HashPosition pos;
524 zval **val;
525
526 ae = ae_ptr;
527 FOREACH_HASH_VAL(pos, allowed_extras, val) {
528 zval *cpy = php_http_zsep(IS_STRING, *val);
529
530 *ae_ptr++ = estrndup(Z_STRVAL_P(cpy), Z_STRLEN_P(cpy));
531 zval_ptr_dtor(&cpy);
532 }
533 *ae_ptr = NULL;
534 }
535
536 switch (Z_TYPE_P(zcookie)) {
537 case IS_ARRAY:
538 case IS_OBJECT:
539 obj->list = php_http_cookie_list_from_struct(obj->list, zcookie TSRMLS_CC);
540 break;
541 default: {
542 zval *cpy = php_http_zsep(IS_STRING, zcookie);
543
544 obj->list = php_http_cookie_list_parse(obj->list, Z_STRVAL_P(cpy), flags, ae TSRMLS_CC);
545 zval_ptr_dtor(&cpy);
546 break;
547 }
548 }
549 } end_error_handling();
550 }
551 }
552 } end_error_handling();
553 }
554
555 PHP_METHOD(HttpCookie, getCookies)
556 {
557 if (SUCCESS == zend_parse_parameters_none()) {
558 php_http_cookie_object_t *obj = zend_object_store_get_object(getThis() TSRMLS_CC);
559
560 array_init(return_value);
561 array_copy(&obj->list->cookies, Z_ARRVAL_P(return_value));
562 return;
563 }
564 RETURN_FALSE;
565 }
566
567 PHP_METHOD(HttpCookie, setCookies)
568 {
569 HashTable *cookies = NULL;
570
571 if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|H", &cookies)) {
572 php_http_cookie_object_t *obj = zend_object_store_get_object(getThis() TSRMLS_CC);
573
574 zend_hash_clean(&obj->list->cookies);
575 if (cookies) {
576 array_copy(cookies, &obj->list->cookies);
577 }
578 RETURN_TRUE;
579 }
580 RETURN_FALSE;
581 }
582
583 PHP_METHOD(HttpCookie, addCookies)
584 {
585 HashTable *cookies = NULL;
586
587 if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "H", &cookies)) {
588 php_http_cookie_object_t *obj = zend_object_store_get_object(getThis() TSRMLS_CC);
589
590 array_join(cookies, &obj->list->cookies, 1, ARRAY_JOIN_STRONLY);
591 RETURN_TRUE;
592 }
593 RETURN_FALSE;
594 }
595
596
597 PHP_METHOD(HttpCookie, getExtras)
598 {
599 if (SUCCESS == zend_parse_parameters_none()) {
600 php_http_cookie_object_t *obj = zend_object_store_get_object(getThis() TSRMLS_CC);
601
602 array_init(return_value);
603 array_copy(&obj->list->extras, Z_ARRVAL_P(return_value));
604 return;
605 }
606 RETURN_FALSE;
607 }
608
609 PHP_METHOD(HttpCookie, setExtras)
610 {
611 HashTable *extras = NULL;
612
613 if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|H", &extras)) {
614 php_http_cookie_object_t *obj = zend_object_store_get_object(getThis() TSRMLS_CC);
615
616 zend_hash_clean(&obj->list->extras);
617 if (extras) {
618 array_copy(extras, &obj->list->extras);
619 }
620 RETURN_TRUE;
621 }
622 RETURN_FALSE;
623 }
624
625 PHP_METHOD(HttpCookie, addExtras)
626 {
627 HashTable *extras = NULL;
628
629 if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "H", &extras)) {
630 php_http_cookie_object_t *obj = zend_object_store_get_object(getThis() TSRMLS_CC);
631
632 array_join(extras, &obj->list->extras, 1, ARRAY_JOIN_STRONLY);
633 RETURN_TRUE;
634 }
635 RETURN_FALSE;
636 }
637
638 PHP_METHOD(HttpCookie, getCookie)
639 {
640 char *name_str;
641 int name_len;
642
643 if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &name_str, &name_len)) {
644 php_http_cookie_object_t *obj = zend_object_store_get_object(getThis() TSRMLS_CC);
645 zval **zvalue;
646
647 if (SUCCESS == zend_hash_find(&obj->list->cookies, name_str, name_len + 1, (void *) &zvalue)) {
648 RETURN_ZVAL(*zvalue, 1, 0);
649 }
650 }
651 RETURN_FALSE;
652 }
653
654 PHP_METHOD(HttpCookie, setCookie)
655 {
656 char *name_str, *value_str;
657 int name_len, value_len;
658
659 if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|s!", &name_str, &name_len, &value_str, &value_len)) {
660 php_http_cookie_object_t *obj = zend_object_store_get_object(getThis() TSRMLS_CC);
661
662 if (!value_str) {
663 RETURN_SUCCESS(zend_hash_del(&obj->list->cookies, name_str, name_len + 1));
664 } else {
665 zval *zvalue;
666
667 MAKE_STD_ZVAL(zvalue);
668 ZVAL_STRINGL(zvalue, value_str, value_len, 1);
669 RETURN_SUCCESS(zend_hash_update(&obj->list->cookies, name_str, name_len + 1, &zvalue, sizeof(zval *), NULL));
670 }
671 }
672 RETURN_FALSE;
673 }
674
675 PHP_METHOD(HttpCookie, addCookie)
676 {
677 char *name_str, *value_str;
678 int name_len, value_len;
679
680 if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|s", &name_str, &name_len, &value_str, &value_len)) {
681 php_http_cookie_object_t *obj = zend_object_store_get_object(getThis() TSRMLS_CC);
682 zval *zvalue;
683
684 MAKE_STD_ZVAL(zvalue);
685 ZVAL_STRINGL(zvalue, value_str, value_len, 1);
686 RETURN_SUCCESS(zend_hash_add(&obj->list->cookies, name_str, name_len + 1, &zvalue, sizeof(zval *), NULL));
687 }
688 RETURN_FALSE;
689 }
690
691 PHP_METHOD(HttpCookie, getExtra)
692 {
693 char *name_str;
694 int name_len;
695
696 if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &name_str, &name_len)) {
697 php_http_cookie_object_t *obj = zend_object_store_get_object(getThis() TSRMLS_CC);
698 zval **zvalue;
699
700 if (SUCCESS == zend_hash_find(&obj->list->extras, name_str, name_len + 1, (void *) &zvalue)) {
701 RETURN_ZVAL(*zvalue, 1, 0);
702 }
703 }
704 RETURN_FALSE;
705 }
706
707 PHP_METHOD(HttpCookie, setExtra)
708 {
709 char *name_str, *value_str;
710 int name_len, value_len;
711
712 if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|s!", &name_str, &name_len, &value_str, &value_len)) {
713 php_http_cookie_object_t *obj = zend_object_store_get_object(getThis() TSRMLS_CC);
714
715 if (!value_str) {
716 RETURN_SUCCESS(zend_hash_del(&obj->list->extras, name_str, name_len + 1));
717 } else {
718 zval *zvalue;
719
720 MAKE_STD_ZVAL(zvalue);
721 ZVAL_STRINGL(zvalue, value_str, value_len, 1);
722 RETURN_SUCCESS(zend_hash_update(&obj->list->extras, name_str, name_len + 1, &zvalue, sizeof(zval *), NULL));
723 }
724 }
725 RETURN_FALSE;
726 }
727
728 PHP_METHOD(HttpCookie, addExtra)
729 {
730 char *name_str, *value_str;
731 int name_len, value_len;
732
733 if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|s", &name_str, &name_len, &value_str, &value_len)) {
734 php_http_cookie_object_t *obj = zend_object_store_get_object(getThis() TSRMLS_CC);
735 zval *zvalue;
736
737 MAKE_STD_ZVAL(zvalue);
738 ZVAL_STRINGL(zvalue, value_str, value_len, 1);
739 RETURN_SUCCESS(zend_hash_add(&obj->list->extras, name_str, name_len + 1, &zvalue, sizeof(zval *), NULL));
740 }
741 RETURN_FALSE;
742 }
743
744 PHP_METHOD(HttpCookie, getDomain)
745 {
746 if (SUCCESS == zend_parse_parameters_none()) {
747 php_http_cookie_object_t *obj = zend_object_store_get_object(getThis() TSRMLS_CC);
748
749 if (obj->list->domain) {
750 RETURN_STRING(obj->list->domain, 1);
751 }
752 RETURN_NULL();
753 }
754 RETURN_FALSE;
755 }
756
757 PHP_METHOD(HttpCookie, setDomain)
758 {
759 char *domain_str = NULL;
760 int domain_len = 0;
761
762 if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|s!", &domain_str, &domain_len)) {
763 php_http_cookie_object_t *obj = zend_object_store_get_object(getThis() TSRMLS_CC);
764
765 STR_SET(obj->list->domain, domain_str ? estrndup(domain_str, domain_len) : NULL);
766 RETURN_TRUE;
767 }
768 RETURN_FALSE;
769 }
770
771 PHP_METHOD(HttpCookie, getPath)
772 {
773 if (SUCCESS == zend_parse_parameters_none()) {
774 php_http_cookie_object_t *obj = zend_object_store_get_object(getThis() TSRMLS_CC);
775
776 if (obj->list->path) {
777 RETURN_STRING(obj->list->path, 1);
778 }
779 RETURN_NULL();
780 }
781 RETURN_FALSE;
782 }
783
784 PHP_METHOD(HttpCookie, setPath)
785 {
786 char *path_str = NULL;
787 int path_len = 0;
788
789 if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|s!", &path_str, &path_len)) {
790 php_http_cookie_object_t *obj = zend_object_store_get_object(getThis() TSRMLS_CC);
791
792 STR_SET(obj->list->path, path_str ? estrndup(path_str, path_len) : NULL);
793 RETURN_TRUE;
794 }
795 RETURN_FALSE;
796 }
797
798 PHP_METHOD(HttpCookie, getExpires)
799 {
800 if (SUCCESS == zend_parse_parameters_none()) {
801 php_http_cookie_object_t *obj = zend_object_store_get_object(getThis() TSRMLS_CC);
802
803 RETURN_LONG(obj->list->expires);
804 }
805 RETURN_FALSE;
806 }
807
808 PHP_METHOD(HttpCookie, setExpires)
809 {
810 long ts = 0;
811
812 if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|l", &ts)) {
813 php_http_cookie_object_t *obj = zend_object_store_get_object(getThis() TSRMLS_CC);
814
815 obj->list->expires = ts;
816 RETURN_TRUE;
817 }
818 RETURN_FALSE;
819 }
820
821 PHP_METHOD(HttpCookie, getFlags)
822 {
823 if (SUCCESS == zend_parse_parameters_none()) {
824 php_http_cookie_object_t *obj = zend_object_store_get_object(getThis() TSRMLS_CC);
825
826 RETURN_LONG(obj->list->flags);
827 }
828 RETURN_FALSE;
829 }
830
831 PHP_METHOD(HttpCookie, setFlags)
832 {
833 long flags = 0;
834
835 if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|l", &flags)) {
836 php_http_cookie_object_t *obj = zend_object_store_get_object(getThis() TSRMLS_CC);
837
838 obj->list->flags = flags;
839 RETURN_TRUE;
840 }
841 RETURN_FALSE;
842 }
843
844 PHP_METHOD(HttpCookie, toString)
845 {
846 if (SUCCESS == zend_parse_parameters_none()) {
847 php_http_cookie_object_t *obj = zend_object_store_get_object(getThis() TSRMLS_CC);
848 char *str;
849 size_t len;
850
851 php_http_cookie_list_to_string(obj->list, &str, &len TSRMLS_CC);
852 RETURN_STRINGL(str, len, 0);
853 }
854 RETURN_EMPTY_STRING();
855 }
856
857 PHP_METHOD(HttpCookie, toArray)
858 {
859 if (SUCCESS == zend_parse_parameters_none()) {
860 php_http_cookie_object_t *obj = zend_object_store_get_object(getThis() TSRMLS_CC);
861
862 array_init(return_value);
863 php_http_cookie_list_to_struct(obj->list, return_value TSRMLS_CC);
864 }
865 }
866
867 PHP_MINIT_FUNCTION(http_cookie)
868 {
869 PHP_HTTP_REGISTER_CLASS(http, Cookie, http_cookie, php_http_object_class_entry, 0);
870 php_http_cookie_class_entry->create_object = php_http_cookie_object_new;
871 memcpy(&php_http_cookie_object_handlers, zend_get_std_object_handlers(), sizeof(zend_object_handlers));
872 php_http_cookie_object_handlers.clone_obj = php_http_cookie_object_clone;
873
874 zend_declare_class_constant_long(php_http_cookie_class_entry, ZEND_STRL("PARSE_RAW"), PHP_HTTP_COOKIE_PARSE_RAW TSRMLS_CC);
875 zend_declare_class_constant_long(php_http_cookie_class_entry, ZEND_STRL("SECURE"), PHP_HTTP_COOKIE_SECURE TSRMLS_CC);
876 zend_declare_class_constant_long(php_http_cookie_class_entry, ZEND_STRL("HTTPONLY"), PHP_HTTP_COOKIE_HTTPONLY TSRMLS_CC);
877
878 return SUCCESS;
879 }
880
881
882
883 /*
884 * Local variables:
885 * tab-width: 4
886 * c-basic-offset: 4
887 * End:
888 * vim600: noet sw=4 ts=4 fdm=marker
889 * vim<600: noet sw=4 ts=4
890 */