include headers where they're needed
[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 PHP_HTTP_API php_http_cookie_list_t *php_http_cookie_list_from_struct(php_http_cookie_list_t *list, zval *strct TSRMLS_DC)
225 {
226 zval **tmp, *cpy;
227 HashTable *ht = HASH_OF(strct);
228
229 list = php_http_cookie_list_init(list TSRMLS_CC);
230
231 if (SUCCESS == zend_hash_find(ht, "cookies", sizeof("cookies"), (void *) &tmp) && Z_TYPE_PP(tmp) == IS_ARRAY) {
232 zend_hash_copy(&list->cookies, Z_ARRVAL_PP(tmp), (copy_ctor_func_t) zval_add_ref, NULL, sizeof(zval *));
233 }
234 if (SUCCESS == zend_hash_find(ht, "extras", sizeof("extras"), (void *) &tmp) && Z_TYPE_PP(tmp) == IS_ARRAY) {
235 zend_hash_copy(&list->extras, Z_ARRVAL_PP(tmp), (copy_ctor_func_t) zval_add_ref, NULL, sizeof(zval *));
236 }
237 if (SUCCESS == zend_hash_find(ht, "flags", sizeof("flags"), (void *) &tmp)) {
238 switch (Z_TYPE_PP(tmp)) {
239 case IS_LONG:
240 list->flags = Z_LVAL_PP(tmp);
241 break;
242 case IS_DOUBLE:
243 list->flags = (long) Z_DVAL_PP(tmp);
244 break;
245 case IS_STRING:
246 cpy = php_http_zsep(IS_LONG, *tmp);
247 list->flags = Z_LVAL_P(cpy);
248 zval_ptr_dtor(&cpy);
249 break;
250 default:
251 break;
252 }
253 }
254 if (SUCCESS == zend_hash_find(ht, "expires", sizeof("expires"), (void *) &tmp)) {
255 switch (Z_TYPE_PP(tmp)) {
256 case IS_LONG:
257 list->expires = Z_LVAL_PP(tmp);
258 break;
259 case IS_DOUBLE:
260 list->expires = (long) Z_DVAL_PP(tmp);
261 break;
262 case IS_STRING:
263 cpy = php_http_zsep(IS_LONG, *tmp);
264 if (Z_LVAL_P(cpy)) {
265 list->expires = Z_LVAL_P(cpy);
266 } else {
267 time_t expires = php_parse_date(Z_STRVAL_PP(tmp), NULL TSRMLS_CC);
268 if (expires > 0) {
269 list->expires = expires;
270 }
271 }
272 zval_ptr_dtor(&cpy);
273 break;
274 default:
275 break;
276 }
277 }
278 if (SUCCESS == zend_hash_find(ht, "path", sizeof("path"), (void *) &tmp) && Z_TYPE_PP(tmp) == IS_STRING) {
279 list->path = estrndup(Z_STRVAL_PP(tmp), Z_STRLEN_PP(tmp));
280 }
281 if (SUCCESS == zend_hash_find(ht, "domain", sizeof("domain"), (void *) &tmp) && Z_TYPE_PP(tmp) == IS_STRING) {
282 list->domain = estrndup(Z_STRVAL_PP(tmp), Z_STRLEN_PP(tmp));
283 }
284
285 return list;
286 }
287
288
289
290 static inline void append_encoded(php_http_buffer *buf, const char *key, size_t key_len, const char *val, size_t val_len)
291 {
292 char *enc_str[2];
293 int enc_len[2];
294
295 enc_str[0] = php_url_encode(key, key_len, &enc_len[0]);
296 enc_str[1] = php_url_encode(val, val_len, &enc_len[1]);
297
298 php_http_buffer_append(buf, enc_str[0], enc_len[0]);
299 php_http_buffer_appends(buf, "=");
300 php_http_buffer_append(buf, enc_str[1], enc_len[1]);
301 php_http_buffer_appends(buf, "; ");
302
303 efree(enc_str[0]);
304 efree(enc_str[1]);
305 }
306
307
308
309 PHP_HTTP_API void php_http_cookie_list_to_string(php_http_cookie_list_t *list, char **str, size_t *len TSRMLS_DC)
310 {
311 php_http_buffer buf;
312 zval **val;
313 php_http_array_hashkey_t key = php_http_array_hashkey_init(0);
314 HashPosition pos;
315
316 php_http_buffer_init(&buf);
317
318 FOREACH_HASH_KEYVAL(pos, &list->cookies, key, val) {
319 if (key.type == HASH_KEY_IS_STRING && key.len) {
320 zval *tmp = php_http_zsep(IS_STRING, *val);
321 append_encoded(&buf, key.str, key.len-1, Z_STRVAL_P(tmp), Z_STRLEN_P(tmp));
322 zval_ptr_dtor(&tmp);
323 }
324 }
325
326 if (list->domain && *list->domain) {
327 php_http_buffer_appendf(&buf, "domain=%s; ", list->domain);
328 }
329 if (list->path && *list->path) {
330 php_http_buffer_appendf(&buf, "path=%s; ", list->path);
331 }
332 if (list->expires) {
333 char *date = php_format_date(ZEND_STRL(PHP_HTTP_DATE_FORMAT), list->expires, 0 TSRMLS_CC);
334 php_http_buffer_appendf(&buf, "expires=%s; ", date);
335 efree(date);
336 }
337
338 FOREACH_HASH_KEYVAL(pos, &list->extras, key, val) {
339 if (key.type == HASH_KEY_IS_STRING && key.len) {
340 zval *tmp = php_http_zsep(IS_STRING, *val);
341 append_encoded(&buf, key.str, key.len-1, Z_STRVAL_P(tmp), Z_STRLEN_P(tmp));
342 }
343 }
344
345 if (list->flags & PHP_HTTP_COOKIE_SECURE) {
346 php_http_buffer_appends(&buf, "secure; ");
347 }
348 if (list->flags & PHP_HTTP_COOKIE_HTTPONLY) {
349 php_http_buffer_appends(&buf, "httpOnly; ");
350 }
351
352 php_http_buffer_fix(&buf);
353 *str = PHP_HTTP_BUFFER_VAL(&buf);
354 *len = PHP_HTTP_BUFFER_LEN(&buf);
355 }
356
357 #define PHP_HTTP_BEGIN_ARGS(method, req_args) PHP_HTTP_BEGIN_ARGS_EX(HttpCookie, method, 0, req_args)
358 #define PHP_HTTP_EMPTY_ARGS(method) PHP_HTTP_EMPTY_ARGS_EX(HttpCookie, method, 0)
359 #define PHP_HTTP_COOKIE_ME(method, visibility) PHP_ME(HttpCookie, method, PHP_HTTP_ARGS(HttpCookie, method), visibility)
360
361 PHP_HTTP_BEGIN_ARGS(__construct, 0)
362 PHP_HTTP_ARG_VAL(cookie_string, 0)
363 PHP_HTTP_ARG_VAL(parser_flags, 0)
364 PHP_HTTP_ARG_VAL(allowed_extras, 0)
365 PHP_HTTP_END_ARGS;
366
367 PHP_HTTP_EMPTY_ARGS(toArray);
368 PHP_HTTP_EMPTY_ARGS(getCookies);
369 PHP_HTTP_EMPTY_ARGS(getExtras);
370 PHP_HTTP_EMPTY_ARGS(getDomain);
371 PHP_HTTP_EMPTY_ARGS(getPath);
372 PHP_HTTP_EMPTY_ARGS(getExpires);
373 PHP_HTTP_EMPTY_ARGS(getFlags);
374 PHP_HTTP_EMPTY_ARGS(toString);
375
376 PHP_HTTP_BEGIN_ARGS(setDomain, 0)
377 PHP_HTTP_ARG_VAL(value, 0)
378 PHP_HTTP_END_ARGS;
379 PHP_HTTP_BEGIN_ARGS(setPath, 0)
380 PHP_HTTP_ARG_VAL(value, 0)
381 PHP_HTTP_END_ARGS;
382 PHP_HTTP_BEGIN_ARGS(setExpires, 0)
383 PHP_HTTP_ARG_VAL(value, 0)
384 PHP_HTTP_END_ARGS;
385 PHP_HTTP_BEGIN_ARGS(setFlags, 0)
386 PHP_HTTP_ARG_VAL(value, 0)
387 PHP_HTTP_END_ARGS;
388
389 PHP_HTTP_BEGIN_ARGS(setCookies, 0)
390 PHP_HTTP_ARG_VAL(cookies, 0)
391 PHP_HTTP_END_ARGS;
392 PHP_HTTP_BEGIN_ARGS(addCookies, 1)
393 PHP_HTTP_ARG_VAL(cookies, 0)
394 PHP_HTTP_END_ARGS;
395 PHP_HTTP_BEGIN_ARGS(setExtras, 0)
396 PHP_HTTP_ARG_VAL(extras, 0)
397 PHP_HTTP_END_ARGS;
398 PHP_HTTP_BEGIN_ARGS(addExtras, 1)
399 PHP_HTTP_ARG_VAL(extras, 0)
400 PHP_HTTP_END_ARGS;
401 PHP_HTTP_BEGIN_ARGS(setCookie, 1)
402 PHP_HTTP_ARG_VAL(cookie_name, 0)
403 PHP_HTTP_ARG_VAL(cookie_value, 0)
404 PHP_HTTP_END_ARGS;
405 PHP_HTTP_BEGIN_ARGS(addCookie, 1)
406 PHP_HTTP_ARG_VAL(cookie_name, 0)
407 PHP_HTTP_ARG_VAL(cookie_value, 0)
408 PHP_HTTP_END_ARGS;
409 PHP_HTTP_BEGIN_ARGS(getCookie, 1)
410 PHP_HTTP_ARG_VAL(name, 0)
411 PHP_HTTP_END_ARGS;
412 PHP_HTTP_BEGIN_ARGS(setExtra, 1)
413 PHP_HTTP_ARG_VAL(extra_name, 0)
414 PHP_HTTP_ARG_VAL(extra_value, 0)
415 PHP_HTTP_END_ARGS;
416 PHP_HTTP_BEGIN_ARGS(addExtra, 1)
417 PHP_HTTP_ARG_VAL(extra_name, 0)
418 PHP_HTTP_ARG_VAL(extra_value, 0)
419 PHP_HTTP_END_ARGS;
420 PHP_HTTP_BEGIN_ARGS(getExtra, 1)
421 PHP_HTTP_ARG_VAL(name, 0)
422 PHP_HTTP_END_ARGS;
423
424 zend_class_entry *php_http_cookie_class_entry;
425 zend_function_entry php_http_cookie_method_entry[] = {
426 PHP_HTTP_COOKIE_ME(__construct, ZEND_ACC_PUBLIC)
427 PHP_HTTP_COOKIE_ME(getCookies, ZEND_ACC_PUBLIC)
428 PHP_HTTP_COOKIE_ME(setCookies, ZEND_ACC_PUBLIC)
429 PHP_HTTP_COOKIE_ME(addCookies, ZEND_ACC_PUBLIC)
430 PHP_HTTP_COOKIE_ME(getCookie, ZEND_ACC_PUBLIC)
431 PHP_HTTP_COOKIE_ME(setCookie, ZEND_ACC_PUBLIC)
432 PHP_HTTP_COOKIE_ME(addCookie, ZEND_ACC_PUBLIC)
433
434 PHP_HTTP_COOKIE_ME(getExtras, ZEND_ACC_PUBLIC)
435 PHP_HTTP_COOKIE_ME(setExtras, ZEND_ACC_PUBLIC)
436 PHP_HTTP_COOKIE_ME(addExtras, ZEND_ACC_PUBLIC)
437 PHP_HTTP_COOKIE_ME(getExtra, ZEND_ACC_PUBLIC)
438 PHP_HTTP_COOKIE_ME(setExtra, ZEND_ACC_PUBLIC)
439 PHP_HTTP_COOKIE_ME(addExtra, ZEND_ACC_PUBLIC)
440
441 PHP_HTTP_COOKIE_ME(getDomain, ZEND_ACC_PUBLIC)
442 PHP_HTTP_COOKIE_ME(setDomain, ZEND_ACC_PUBLIC)
443 PHP_HTTP_COOKIE_ME(getPath, ZEND_ACC_PUBLIC)
444 PHP_HTTP_COOKIE_ME(setPath, ZEND_ACC_PUBLIC)
445 PHP_HTTP_COOKIE_ME(getExpires, ZEND_ACC_PUBLIC)
446 PHP_HTTP_COOKIE_ME(setExpires, ZEND_ACC_PUBLIC)
447 PHP_HTTP_COOKIE_ME(getFlags, ZEND_ACC_PUBLIC)
448 PHP_HTTP_COOKIE_ME(setFlags, ZEND_ACC_PUBLIC)
449
450 PHP_HTTP_COOKIE_ME(toArray, ZEND_ACC_PUBLIC)
451 PHP_HTTP_COOKIE_ME(toString, ZEND_ACC_PUBLIC)
452 ZEND_MALIAS(HttpCookie, __toString, toString, PHP_HTTP_ARGS(HttpCookie, toString), ZEND_ACC_PUBLIC)
453
454 EMPTY_FUNCTION_ENTRY
455 };
456 static zend_object_handlers php_http_cookie_object_handlers;
457
458 zend_object_value php_http_cookie_object_new(zend_class_entry *ce TSRMLS_DC)
459 {
460 return php_http_cookie_object_new_ex(ce, NULL, NULL TSRMLS_CC);
461 }
462
463 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)
464 {
465 zend_object_value ov;
466 php_http_cookie_object_t *o;
467
468 o = ecalloc(sizeof(*o), 1);
469 zend_object_std_init((zend_object *) o, ce TSRMLS_CC);
470 object_properties_init((zend_object *) o, ce);
471
472 if (list) {
473 o->list = list;
474 }
475
476 if (ptr) {
477 *ptr = o;
478 }
479
480 ov.handle = zend_objects_store_put(o, NULL, php_http_cookie_object_free, NULL TSRMLS_CC);
481 ov.handlers = &php_http_cookie_object_handlers;
482
483 return ov;
484 }
485
486 zend_object_value php_http_cookie_object_clone(zval *this_ptr TSRMLS_CC)
487 {
488 php_http_cookie_object_t *new_obj, *old_obj = zend_object_store_get_object(getThis() TSRMLS_CC);
489 zend_object_value ov;
490
491 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);
492 zend_objects_clone_members((zend_object *) new_obj, ov, (zend_object *) old_obj, Z_OBJ_HANDLE_P(getThis()) TSRMLS_CC);
493
494 return ov;
495 }
496
497 void php_http_cookie_object_free(void *object TSRMLS_CC)
498 {
499 php_http_cookie_object_t *obj = object;
500
501 php_http_cookie_list_free(&obj->list TSRMLS_CC);
502 zend_object_std_dtor((zend_object *) obj TSRMLS_CC);
503 efree(obj);
504 }
505
506 PHP_METHOD(HttpCookie, __construct)
507 {
508 with_error_handling(EH_THROW, PHP_HTTP_EX_CE(runtime)) {
509 zval *zcookie = NULL;
510 long flags = 0;
511 HashTable *allowed_extras = NULL;
512
513 if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|z!lH", &zcookie, &flags, &allowed_extras)) {
514 if (zcookie) {
515 with_error_handling(EH_THROW, PHP_HTTP_EX_CE(cookie)) {
516 char **ae = NULL;
517 php_http_cookie_object_t *obj = zend_object_store_get_object(getThis() TSRMLS_CC);
518
519 if (allowed_extras && zend_hash_num_elements(allowed_extras)) {
520 char **ae_ptr = safe_emalloc(zend_hash_num_elements(allowed_extras) + 1, sizeof(char *), 0);
521 HashPosition pos;
522 zval **val;
523
524 ae = ae_ptr;
525 FOREACH_HASH_VAL(pos, allowed_extras, val) {
526 zval *cpy = php_http_zsep(IS_STRING, *val);
527
528 *ae_ptr++ = estrndup(Z_STRVAL_P(cpy), Z_STRLEN_P(cpy));
529 zval_ptr_dtor(&cpy);
530 }
531 *ae_ptr = NULL;
532 }
533
534 switch (Z_TYPE_P(zcookie)) {
535 case IS_ARRAY:
536 case IS_OBJECT:
537 obj->list = php_http_cookie_list_from_struct(obj->list, zcookie TSRMLS_CC);
538 break;
539 default: {
540 zval *cpy = php_http_zsep(IS_STRING, zcookie);
541
542 obj->list = php_http_cookie_list_parse(obj->list, Z_STRVAL_P(cpy), flags, ae TSRMLS_CC);
543 zval_ptr_dtor(&cpy);
544 break;
545 }
546 }
547 } end_error_handling();
548 }
549 }
550 } end_error_handling();
551 }
552
553 PHP_METHOD(HttpCookie, getCookies)
554 {
555 if (SUCCESS == zend_parse_parameters_none()) {
556 php_http_cookie_object_t *obj = zend_object_store_get_object(getThis() TSRMLS_CC);
557
558 array_init(return_value);
559 array_copy(&obj->list->cookies, Z_ARRVAL_P(return_value));
560 return;
561 }
562 RETURN_FALSE;
563 }
564
565 PHP_METHOD(HttpCookie, setCookies)
566 {
567 HashTable *cookies = NULL;
568
569 if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|H", &cookies)) {
570 php_http_cookie_object_t *obj = zend_object_store_get_object(getThis() TSRMLS_CC);
571
572 zend_hash_clean(&obj->list->cookies);
573 if (cookies) {
574 array_copy(cookies, &obj->list->cookies);
575 }
576 RETURN_TRUE;
577 }
578 RETURN_FALSE;
579 }
580
581 PHP_METHOD(HttpCookie, addCookies)
582 {
583 HashTable *cookies = NULL;
584
585 if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "H", &cookies)) {
586 php_http_cookie_object_t *obj = zend_object_store_get_object(getThis() TSRMLS_CC);
587
588 array_join(cookies, &obj->list->cookies, 1, ARRAY_JOIN_STRONLY);
589 RETURN_TRUE;
590 }
591 RETURN_FALSE;
592 }
593
594
595 PHP_METHOD(HttpCookie, getExtras)
596 {
597 if (SUCCESS == zend_parse_parameters_none()) {
598 php_http_cookie_object_t *obj = zend_object_store_get_object(getThis() TSRMLS_CC);
599
600 array_init(return_value);
601 array_copy(&obj->list->extras, Z_ARRVAL_P(return_value));
602 return;
603 }
604 RETURN_FALSE;
605 }
606
607 PHP_METHOD(HttpCookie, setExtras)
608 {
609 HashTable *extras = NULL;
610
611 if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|H", &extras)) {
612 php_http_cookie_object_t *obj = zend_object_store_get_object(getThis() TSRMLS_CC);
613
614 zend_hash_clean(&obj->list->extras);
615 if (extras) {
616 array_copy(extras, &obj->list->extras);
617 }
618 RETURN_TRUE;
619 }
620 RETURN_FALSE;
621 }
622
623 PHP_METHOD(HttpCookie, addExtras)
624 {
625 HashTable *extras = NULL;
626
627 if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "H", &extras)) {
628 php_http_cookie_object_t *obj = zend_object_store_get_object(getThis() TSRMLS_CC);
629
630 array_join(extras, &obj->list->extras, 1, ARRAY_JOIN_STRONLY);
631 RETURN_TRUE;
632 }
633 RETURN_FALSE;
634 }
635
636 PHP_METHOD(HttpCookie, getCookie)
637 {
638 char *name_str;
639 int name_len;
640
641 if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &name_str, &name_len)) {
642 php_http_cookie_object_t *obj = zend_object_store_get_object(getThis() TSRMLS_CC);
643 zval **zvalue;
644
645 if (SUCCESS == zend_hash_find(&obj->list->cookies, name_str, name_len + 1, (void *) &zvalue)) {
646 RETURN_ZVAL(*zvalue, 1, 0);
647 }
648 }
649 RETURN_FALSE;
650 }
651
652 PHP_METHOD(HttpCookie, setCookie)
653 {
654 char *name_str, *value_str;
655 int name_len, value_len;
656
657 if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|s!", &name_str, &name_len, &value_str, &value_len)) {
658 php_http_cookie_object_t *obj = zend_object_store_get_object(getThis() TSRMLS_CC);
659
660 if (!value_str) {
661 RETURN_SUCCESS(zend_hash_del(&obj->list->cookies, name_str, name_len + 1));
662 } else {
663 zval *zvalue;
664
665 MAKE_STD_ZVAL(zvalue);
666 ZVAL_STRINGL(zvalue, value_str, value_len, 1);
667 RETURN_SUCCESS(zend_hash_update(&obj->list->cookies, name_str, name_len + 1, &zvalue, sizeof(zval *), NULL));
668 }
669 }
670 RETURN_FALSE;
671 }
672
673 PHP_METHOD(HttpCookie, addCookie)
674 {
675 char *name_str, *value_str;
676 int name_len, value_len;
677
678 if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|s", &name_str, &name_len, &value_str, &value_len)) {
679 php_http_cookie_object_t *obj = zend_object_store_get_object(getThis() TSRMLS_CC);
680 zval *zvalue;
681
682 MAKE_STD_ZVAL(zvalue);
683 ZVAL_STRINGL(zvalue, value_str, value_len, 1);
684 RETURN_SUCCESS(zend_hash_add(&obj->list->cookies, name_str, name_len + 1, &zvalue, sizeof(zval *), NULL));
685 }
686 RETURN_FALSE;
687 }
688
689 PHP_METHOD(HttpCookie, getExtra)
690 {
691 char *name_str;
692 int name_len;
693
694 if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &name_str, &name_len)) {
695 php_http_cookie_object_t *obj = zend_object_store_get_object(getThis() TSRMLS_CC);
696 zval **zvalue;
697
698 if (SUCCESS == zend_hash_find(&obj->list->extras, name_str, name_len + 1, (void *) &zvalue)) {
699 RETURN_ZVAL(*zvalue, 1, 0);
700 }
701 }
702 RETURN_FALSE;
703 }
704
705 PHP_METHOD(HttpCookie, setExtra)
706 {
707 char *name_str, *value_str;
708 int name_len, value_len;
709
710 if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|s!", &name_str, &name_len, &value_str, &value_len)) {
711 php_http_cookie_object_t *obj = zend_object_store_get_object(getThis() TSRMLS_CC);
712
713 if (!value_str) {
714 RETURN_SUCCESS(zend_hash_del(&obj->list->extras, name_str, name_len + 1));
715 } else {
716 zval *zvalue;
717
718 MAKE_STD_ZVAL(zvalue);
719 ZVAL_STRINGL(zvalue, value_str, value_len, 1);
720 RETURN_SUCCESS(zend_hash_update(&obj->list->extras, name_str, name_len + 1, &zvalue, sizeof(zval *), NULL));
721 }
722 }
723 RETURN_FALSE;
724 }
725
726 PHP_METHOD(HttpCookie, addExtra)
727 {
728 char *name_str, *value_str;
729 int name_len, value_len;
730
731 if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|s", &name_str, &name_len, &value_str, &value_len)) {
732 php_http_cookie_object_t *obj = zend_object_store_get_object(getThis() TSRMLS_CC);
733 zval *zvalue;
734
735 MAKE_STD_ZVAL(zvalue);
736 ZVAL_STRINGL(zvalue, value_str, value_len, 1);
737 RETURN_SUCCESS(zend_hash_add(&obj->list->extras, name_str, name_len + 1, &zvalue, sizeof(zval *), NULL));
738 }
739 RETURN_FALSE;
740 }
741
742 PHP_METHOD(HttpCookie, getDomain)
743 {
744 if (SUCCESS == zend_parse_parameters_none()) {
745 php_http_cookie_object_t *obj = zend_object_store_get_object(getThis() TSRMLS_CC);
746
747 if (obj->list->domain) {
748 RETURN_STRING(obj->list->domain, 1);
749 }
750 RETURN_NULL();
751 }
752 RETURN_FALSE;
753 }
754
755 PHP_METHOD(HttpCookie, setDomain)
756 {
757 char *domain_str = NULL;
758 int domain_len = 0;
759
760 if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|s!", &domain_str, &domain_len)) {
761 php_http_cookie_object_t *obj = zend_object_store_get_object(getThis() TSRMLS_CC);
762
763 STR_SET(obj->list->domain, domain_str ? estrndup(domain_str, domain_len) : NULL);
764 RETURN_TRUE;
765 }
766 RETURN_FALSE;
767 }
768
769 PHP_METHOD(HttpCookie, getPath)
770 {
771 if (SUCCESS == zend_parse_parameters_none()) {
772 php_http_cookie_object_t *obj = zend_object_store_get_object(getThis() TSRMLS_CC);
773
774 if (obj->list->path) {
775 RETURN_STRING(obj->list->path, 1);
776 }
777 RETURN_NULL();
778 }
779 RETURN_FALSE;
780 }
781
782 PHP_METHOD(HttpCookie, setPath)
783 {
784 char *path_str = NULL;
785 int path_len = 0;
786
787 if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|s!", &path_str, &path_len)) {
788 php_http_cookie_object_t *obj = zend_object_store_get_object(getThis() TSRMLS_CC);
789
790 STR_SET(obj->list->path, path_str ? estrndup(path_str, path_len) : NULL);
791 RETURN_TRUE;
792 }
793 RETURN_FALSE;
794 }
795
796 PHP_METHOD(HttpCookie, getExpires)
797 {
798 if (SUCCESS == zend_parse_parameters_none()) {
799 php_http_cookie_object_t *obj = zend_object_store_get_object(getThis() TSRMLS_CC);
800
801 RETURN_LONG(obj->list->expires);
802 }
803 RETURN_FALSE;
804 }
805
806 PHP_METHOD(HttpCookie, setExpires)
807 {
808 long ts = 0;
809
810 if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|l", &ts)) {
811 php_http_cookie_object_t *obj = zend_object_store_get_object(getThis() TSRMLS_CC);
812
813 obj->list->expires = ts;
814 RETURN_TRUE;
815 }
816 RETURN_FALSE;
817 }
818
819 PHP_METHOD(HttpCookie, getFlags)
820 {
821 if (SUCCESS == zend_parse_parameters_none()) {
822 php_http_cookie_object_t *obj = zend_object_store_get_object(getThis() TSRMLS_CC);
823
824 RETURN_LONG(obj->list->flags);
825 }
826 RETURN_FALSE;
827 }
828
829 PHP_METHOD(HttpCookie, setFlags)
830 {
831 long flags = 0;
832
833 if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|l", &flags)) {
834 php_http_cookie_object_t *obj = zend_object_store_get_object(getThis() TSRMLS_CC);
835
836 obj->list->flags = flags;
837 RETURN_TRUE;
838 }
839 RETURN_FALSE;
840 }
841
842 PHP_METHOD(HttpCookie, toString)
843 {
844 if (SUCCESS == zend_parse_parameters_none()) {
845 php_http_cookie_object_t *obj = zend_object_store_get_object(getThis() TSRMLS_CC);
846 char *str;
847 size_t len;
848
849 php_http_cookie_list_to_string(obj->list, &str, &len TSRMLS_CC);
850 RETURN_STRINGL(str, len, 0);
851 }
852 RETURN_EMPTY_STRING();
853 }
854
855 PHP_METHOD(HttpCookie, toArray)
856 {
857 if (SUCCESS == zend_parse_parameters_none()) {
858 php_http_cookie_object_t *obj = zend_object_store_get_object(getThis() TSRMLS_CC);
859
860 array_init(return_value);
861 php_http_cookie_list_to_struct(obj->list, return_value TSRMLS_CC);
862 }
863 }
864
865 PHP_MINIT_FUNCTION(http_cookie)
866 {
867 PHP_HTTP_REGISTER_CLASS(http, Cookie, http_cookie, php_http_object_class_entry, 0);
868 php_http_cookie_class_entry->create_object = php_http_cookie_object_new;
869 memcpy(&php_http_cookie_object_handlers, zend_get_std_object_handlers(), sizeof(zend_object_handlers));
870 php_http_cookie_object_handlers.clone_obj = php_http_cookie_object_clone;
871
872 zend_declare_class_constant_long(php_http_cookie_class_entry, ZEND_STRL("PARSE_RAW"), PHP_HTTP_COOKIE_PARSE_RAW TSRMLS_CC);
873 zend_declare_class_constant_long(php_http_cookie_class_entry, ZEND_STRL("SECURE"), PHP_HTTP_COOKIE_SECURE TSRMLS_CC);
874 zend_declare_class_constant_long(php_http_cookie_class_entry, ZEND_STRL("HTTPONLY"), PHP_HTTP_COOKIE_HTTPONLY TSRMLS_CC);
875
876 return SUCCESS;
877 }
878
879
880
881 /*
882 * Local variables:
883 * tab-width: 4
884 * c-basic-offset: 4
885 * End:
886 * vim600: noet sw=4 ts=4 fdm=marker
887 * vim<600: noet sw=4 ts=4
888 */