Return to session.c CVS log | Up to [ELWIX - Embedded LightWeight unIX -] / embedaddon / php / ext / session |
1.1 ! misho 1: /* ! 2: +----------------------------------------------------------------------+ ! 3: | PHP Version 5 | ! 4: +----------------------------------------------------------------------+ ! 5: | Copyright (c) 1997-2012 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: | Authors: Sascha Schumann <sascha@schumann.cx> | ! 16: | Andrei Zmievski <andrei@php.net> | ! 17: +----------------------------------------------------------------------+ ! 18: */ ! 19: ! 20: /* $Id: session.c 321634 2012-01-01 13:15:04Z felipe $ */ ! 21: ! 22: #ifdef HAVE_CONFIG_H ! 23: #include "config.h" ! 24: #endif ! 25: ! 26: #include "php.h" ! 27: ! 28: #ifdef PHP_WIN32 ! 29: # include "win32/winutil.h" ! 30: # include "win32/time.h" ! 31: #else ! 32: #include <sys/time.h> ! 33: #endif ! 34: ! 35: #include <sys/stat.h> ! 36: #include <fcntl.h> ! 37: ! 38: #include "php_ini.h" ! 39: #include "SAPI.h" ! 40: #include "php_session.h" ! 41: #include "ext/standard/md5.h" ! 42: #include "ext/standard/sha1.h" ! 43: #include "ext/standard/php_var.h" ! 44: #include "ext/date/php_date.h" ! 45: #include "ext/standard/php_lcg.h" ! 46: #include "ext/standard/url_scanner_ex.h" ! 47: #include "ext/standard/php_rand.h" /* for RAND_MAX */ ! 48: #include "ext/standard/info.h" ! 49: #include "ext/standard/php_smart_str.h" ! 50: #include "ext/standard/url.h" ! 51: ! 52: #include "mod_files.h" ! 53: #include "mod_user.h" ! 54: ! 55: #ifdef HAVE_LIBMM ! 56: #include "mod_mm.h" ! 57: #endif ! 58: ! 59: PHPAPI ZEND_DECLARE_MODULE_GLOBALS(ps); ! 60: ! 61: /* *********** ! 62: * Helpers * ! 63: *********** */ ! 64: ! 65: #define IF_SESSION_VARS() \ ! 66: if (PS(http_session_vars) && PS(http_session_vars)->type == IS_ARRAY) ! 67: ! 68: #define SESSION_CHECK_ACTIVE_STATE \ ! 69: if (PS(session_status) == php_session_active) { \ ! 70: php_error_docref(NULL TSRMLS_CC, E_WARNING, "A session is active. You cannot change the session module's ini settings at this time"); \ ! 71: return FAILURE; \ ! 72: } ! 73: ! 74: /* Dispatched by RINIT and by php_session_destroy */ ! 75: static inline void php_rinit_session_globals(TSRMLS_D) /* {{{ */ ! 76: { ! 77: PS(id) = NULL; ! 78: PS(session_status) = php_session_none; ! 79: PS(mod_data) = NULL; ! 80: /* Do NOT init PS(mod_user_names) here! */ ! 81: PS(http_session_vars) = NULL; ! 82: } ! 83: /* }}} */ ! 84: ! 85: /* Dispatched by RSHUTDOWN and by php_session_destroy */ ! 86: static inline void php_rshutdown_session_globals(TSRMLS_D) /* {{{ */ ! 87: { ! 88: if (PS(http_session_vars)) { ! 89: zval_ptr_dtor(&PS(http_session_vars)); ! 90: PS(http_session_vars) = NULL; ! 91: } ! 92: /* Do NOT destroy PS(mod_user_names) here! */ ! 93: if (PS(mod_data)) { ! 94: zend_try { ! 95: PS(mod)->s_close(&PS(mod_data) TSRMLS_CC); ! 96: } zend_end_try(); ! 97: } ! 98: if (PS(id)) { ! 99: efree(PS(id)); ! 100: } ! 101: } ! 102: /* }}} */ ! 103: ! 104: static int php_session_destroy(TSRMLS_D) /* {{{ */ ! 105: { ! 106: int retval = SUCCESS; ! 107: ! 108: if (PS(session_status) != php_session_active) { ! 109: php_error_docref(NULL TSRMLS_CC, E_WARNING, "Trying to destroy uninitialized session"); ! 110: return FAILURE; ! 111: } ! 112: ! 113: if (PS(mod)->s_destroy(&PS(mod_data), PS(id) TSRMLS_CC) == FAILURE) { ! 114: retval = FAILURE; ! 115: php_error_docref(NULL TSRMLS_CC, E_WARNING, "Session object destruction failed"); ! 116: } ! 117: ! 118: php_rshutdown_session_globals(TSRMLS_C); ! 119: php_rinit_session_globals(TSRMLS_C); ! 120: ! 121: return retval; ! 122: } ! 123: /* }}} */ ! 124: ! 125: PHPAPI void php_add_session_var(char *name, size_t namelen TSRMLS_DC) /* {{{ */ ! 126: { ! 127: zval **sym_track = NULL; ! 128: ! 129: IF_SESSION_VARS() { ! 130: zend_hash_find(Z_ARRVAL_P(PS(http_session_vars)), name, namelen + 1, (void *) &sym_track); ! 131: } else { ! 132: return; ! 133: } ! 134: ! 135: /* Set up a proper reference between $_SESSION["x"] and $x. */ ! 136: ! 137: if (PG(register_globals)) { ! 138: zval **sym_global = NULL; ! 139: ! 140: if (zend_hash_find(&EG(symbol_table), name, namelen + 1, (void *) &sym_global) == SUCCESS) { ! 141: if ((Z_TYPE_PP(sym_global) == IS_ARRAY && Z_ARRVAL_PP(sym_global) == &EG(symbol_table)) || *sym_global == PS(http_session_vars)) { ! 142: return; ! 143: } ! 144: } ! 145: ! 146: if (sym_global == NULL && sym_track == NULL) { ! 147: zval *empty_var; ! 148: ! 149: ALLOC_INIT_ZVAL(empty_var); /* this sets refcount to 1 */ ! 150: Z_SET_REFCOUNT_P(empty_var, 0); /* our module does not maintain a ref */ ! 151: /* The next call will increase refcount by NR_OF_SYM_TABLES==2 */ ! 152: zend_set_hash_symbol(empty_var, name, namelen, 1, 2, Z_ARRVAL_P(PS(http_session_vars)), &EG(symbol_table)); ! 153: } else if (sym_global == NULL) { ! 154: SEPARATE_ZVAL_IF_NOT_REF(sym_track); ! 155: zend_set_hash_symbol(*sym_track, name, namelen, 1, 1, &EG(symbol_table)); ! 156: } else if (sym_track == NULL) { ! 157: SEPARATE_ZVAL_IF_NOT_REF(sym_global); ! 158: zend_set_hash_symbol(*sym_global, name, namelen, 1, 1, Z_ARRVAL_P(PS(http_session_vars))); ! 159: } ! 160: } else { ! 161: if (sym_track == NULL) { ! 162: zval *empty_var; ! 163: ! 164: ALLOC_INIT_ZVAL(empty_var); ! 165: ZEND_SET_SYMBOL_WITH_LENGTH(Z_ARRVAL_P(PS(http_session_vars)), name, namelen+1, empty_var, 1, 0); ! 166: } ! 167: } ! 168: } ! 169: /* }}} */ ! 170: ! 171: PHPAPI void php_set_session_var(char *name, size_t namelen, zval *state_val, php_unserialize_data_t *var_hash TSRMLS_DC) /* {{{ */ ! 172: { ! 173: if (PG(register_globals)) { ! 174: zval **old_symbol; ! 175: if (zend_hash_find(&EG(symbol_table),name,namelen+1,(void *)&old_symbol) == SUCCESS) { ! 176: if ((Z_TYPE_PP(old_symbol) == IS_ARRAY && Z_ARRVAL_PP(old_symbol) == &EG(symbol_table)) || *old_symbol == PS(http_session_vars)) { ! 177: return; ! 178: } ! 179: ! 180: /* A global symbol with the same name exists already. That ! 181: * symbol might have been created by other means (e.g. $_GET). ! 182: * ! 183: * hash_update in zend_set_hash_symbol is not good, because ! 184: * it will leave referenced variables (such as local instances ! 185: * of a global variable) dangling. ! 186: * ! 187: * BTW: if you use register_globals references between ! 188: * session-vars won't work because of this very reason! */ ! 189: ! 190: REPLACE_ZVAL_VALUE(old_symbol,state_val,1); ! 191: ! 192: /* The following line will update the reference table used for ! 193: * unserialization. It is optional, because some storage ! 194: * formats may not be able to represent references. */ ! 195: ! 196: if (var_hash) { ! 197: PHP_VAR_UNSERIALIZE_ZVAL_CHANGED(var_hash,state_val,*old_symbol); ! 198: } ! 199: ! 200: zend_set_hash_symbol(*old_symbol, name, namelen, 1, 1, Z_ARRVAL_P(PS(http_session_vars))); ! 201: } else { ! 202: zend_set_hash_symbol(state_val, name, namelen, 1, 2, Z_ARRVAL_P(PS(http_session_vars)), &EG(symbol_table)); ! 203: } ! 204: } else IF_SESSION_VARS() { ! 205: zend_set_hash_symbol(state_val, name, namelen, PZVAL_IS_REF(state_val), 1, Z_ARRVAL_P(PS(http_session_vars))); ! 206: } ! 207: } ! 208: /* }}} */ ! 209: ! 210: PHPAPI int php_get_session_var(char *name, size_t namelen, zval ***state_var TSRMLS_DC) /* {{{ */ ! 211: { ! 212: int ret = FAILURE; ! 213: ! 214: IF_SESSION_VARS() { ! 215: ret = zend_hash_find(Z_ARRVAL_P(PS(http_session_vars)), name, namelen + 1, (void **) state_var); ! 216: ! 217: /* If register_globals is enabled, and ! 218: * if there is an entry for the slot in $_SESSION, and ! 219: * if that entry is still set to NULL, and ! 220: * if the global var exists, then ! 221: * we prefer the same key in the global sym table. */ ! 222: ! 223: if (PG(register_globals) && ret == SUCCESS && Z_TYPE_PP(*state_var) == IS_NULL) { ! 224: zval **tmp; ! 225: ! 226: if (zend_hash_find(&EG(symbol_table), name, namelen + 1, (void **) &tmp) == SUCCESS) { ! 227: *state_var = tmp; ! 228: } ! 229: } ! 230: } ! 231: return ret; ! 232: } ! 233: /* }}} */ ! 234: ! 235: static void php_session_track_init(TSRMLS_D) /* {{{ */ ! 236: { ! 237: zval *session_vars = NULL; ! 238: ! 239: /* Unconditionally destroy existing arrays -- possible dirty data */ ! 240: zend_delete_global_variable("HTTP_SESSION_VARS", sizeof("HTTP_SESSION_VARS")-1 TSRMLS_CC); ! 241: zend_delete_global_variable("_SESSION", sizeof("_SESSION")-1 TSRMLS_CC); ! 242: ! 243: if (PS(http_session_vars)) { ! 244: zval_ptr_dtor(&PS(http_session_vars)); ! 245: } ! 246: ! 247: MAKE_STD_ZVAL(session_vars); ! 248: array_init(session_vars); ! 249: PS(http_session_vars) = session_vars; ! 250: ! 251: if (PG(register_long_arrays)) { ! 252: ZEND_SET_GLOBAL_VAR_WITH_LENGTH("HTTP_SESSION_VARS", sizeof("HTTP_SESSION_VARS"), PS(http_session_vars), 3, 1); ! 253: ZEND_SET_GLOBAL_VAR_WITH_LENGTH("_SESSION", sizeof("_SESSION"), PS(http_session_vars), 3, 1); ! 254: } ! 255: else { ! 256: ZEND_SET_GLOBAL_VAR_WITH_LENGTH("_SESSION", sizeof("_SESSION"), PS(http_session_vars), 2, 1); ! 257: } ! 258: } ! 259: /* }}} */ ! 260: ! 261: static char *php_session_encode(int *newlen TSRMLS_DC) /* {{{ */ ! 262: { ! 263: char *ret = NULL; ! 264: ! 265: IF_SESSION_VARS() { ! 266: if (!PS(serializer)) { ! 267: php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unknown session.serialize_handler. Failed to encode session object"); ! 268: ret = NULL; ! 269: } else if (PS(serializer)->encode(&ret, newlen TSRMLS_CC) == FAILURE) { ! 270: ret = NULL; ! 271: } ! 272: } else { ! 273: php_error_docref(NULL TSRMLS_CC, E_WARNING, "Cannot encode non-existent session"); ! 274: } ! 275: return ret; ! 276: } ! 277: /* }}} */ ! 278: ! 279: static void php_session_decode(const char *val, int vallen TSRMLS_DC) /* {{{ */ ! 280: { ! 281: if (!PS(serializer)) { ! 282: php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unknown session.serialize_handler. Failed to decode session object"); ! 283: return; ! 284: } ! 285: if (PS(serializer)->decode(val, vallen TSRMLS_CC) == FAILURE) { ! 286: php_session_destroy(TSRMLS_C); ! 287: php_error_docref(NULL TSRMLS_CC, E_WARNING, "Failed to decode session object. Session has been destroyed"); ! 288: } ! 289: } ! 290: /* }}} */ ! 291: ! 292: /* ! 293: * Note that we cannot use the BASE64 alphabet here, because ! 294: * it contains "/" and "+": both are unacceptable for simple inclusion ! 295: * into URLs. ! 296: */ ! 297: ! 298: static char hexconvtab[] = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ,-"; ! 299: ! 300: enum { ! 301: PS_HASH_FUNC_MD5, ! 302: PS_HASH_FUNC_SHA1, ! 303: PS_HASH_FUNC_OTHER ! 304: }; ! 305: ! 306: /* returns a pointer to the byte after the last valid character in out */ ! 307: static char *bin_to_readable(char *in, size_t inlen, char *out, char nbits) /* {{{ */ ! 308: { ! 309: unsigned char *p, *q; ! 310: unsigned short w; ! 311: int mask; ! 312: int have; ! 313: ! 314: p = (unsigned char *) in; ! 315: q = (unsigned char *)in + inlen; ! 316: ! 317: w = 0; ! 318: have = 0; ! 319: mask = (1 << nbits) - 1; ! 320: ! 321: while (1) { ! 322: if (have < nbits) { ! 323: if (p < q) { ! 324: w |= *p++ << have; ! 325: have += 8; ! 326: } else { ! 327: /* consumed everything? */ ! 328: if (have == 0) break; ! 329: /* No? We need a final round */ ! 330: have = nbits; ! 331: } ! 332: } ! 333: ! 334: /* consume nbits */ ! 335: *out++ = hexconvtab[w & mask]; ! 336: w >>= nbits; ! 337: have -= nbits; ! 338: } ! 339: ! 340: *out = '\0'; ! 341: return out; ! 342: } ! 343: /* }}} */ ! 344: ! 345: PHPAPI char *php_session_create_id(PS_CREATE_SID_ARGS) /* {{{ */ ! 346: { ! 347: PHP_MD5_CTX md5_context; ! 348: PHP_SHA1_CTX sha1_context; ! 349: #if defined(HAVE_HASH_EXT) && !defined(COMPILE_DL_HASH) ! 350: void *hash_context; ! 351: #endif ! 352: unsigned char *digest; ! 353: int digest_len; ! 354: int j; ! 355: char *buf, *outid; ! 356: struct timeval tv; ! 357: zval **array; ! 358: zval **token; ! 359: char *remote_addr = NULL; ! 360: ! 361: gettimeofday(&tv, NULL); ! 362: ! 363: if (zend_hash_find(&EG(symbol_table), "_SERVER", sizeof("_SERVER"), (void **) &array) == SUCCESS && ! 364: Z_TYPE_PP(array) == IS_ARRAY && ! 365: zend_hash_find(Z_ARRVAL_PP(array), "REMOTE_ADDR", sizeof("REMOTE_ADDR"), (void **) &token) == SUCCESS ! 366: ) { ! 367: remote_addr = Z_STRVAL_PP(token); ! 368: } ! 369: ! 370: /* maximum 15+19+19+10 bytes */ ! 371: spprintf(&buf, 0, "%.15s%ld%ld%0.8F", remote_addr ? remote_addr : "", tv.tv_sec, (long int)tv.tv_usec, php_combined_lcg(TSRMLS_C) * 10); ! 372: ! 373: switch (PS(hash_func)) { ! 374: case PS_HASH_FUNC_MD5: ! 375: PHP_MD5Init(&md5_context); ! 376: PHP_MD5Update(&md5_context, (unsigned char *) buf, strlen(buf)); ! 377: digest_len = 16; ! 378: break; ! 379: case PS_HASH_FUNC_SHA1: ! 380: PHP_SHA1Init(&sha1_context); ! 381: PHP_SHA1Update(&sha1_context, (unsigned char *) buf, strlen(buf)); ! 382: digest_len = 20; ! 383: break; ! 384: #if defined(HAVE_HASH_EXT) && !defined(COMPILE_DL_HASH) ! 385: case PS_HASH_FUNC_OTHER: ! 386: if (!PS(hash_ops)) { ! 387: php_error_docref(NULL TSRMLS_CC, E_ERROR, "Invalid session hash function"); ! 388: efree(buf); ! 389: return NULL; ! 390: } ! 391: ! 392: hash_context = emalloc(PS(hash_ops)->context_size); ! 393: PS(hash_ops)->hash_init(hash_context); ! 394: PS(hash_ops)->hash_update(hash_context, (unsigned char *) buf, strlen(buf)); ! 395: digest_len = PS(hash_ops)->digest_size; ! 396: break; ! 397: #endif /* HAVE_HASH_EXT */ ! 398: default: ! 399: php_error_docref(NULL TSRMLS_CC, E_ERROR, "Invalid session hash function"); ! 400: efree(buf); ! 401: return NULL; ! 402: } ! 403: efree(buf); ! 404: ! 405: if (PS(entropy_length) > 0) { ! 406: #ifdef PHP_WIN32 ! 407: unsigned char rbuf[2048]; ! 408: size_t toread = PS(entropy_length); ! 409: ! 410: if (php_win32_get_random_bytes(rbuf, (size_t) toread) == SUCCESS){ ! 411: ! 412: switch (PS(hash_func)) { ! 413: case PS_HASH_FUNC_MD5: ! 414: PHP_MD5Update(&md5_context, rbuf, toread); ! 415: break; ! 416: case PS_HASH_FUNC_SHA1: ! 417: PHP_SHA1Update(&sha1_context, rbuf, toread); ! 418: break; ! 419: # if defined(HAVE_HASH_EXT) && !defined(COMPILE_DL_HASH) ! 420: case PS_HASH_FUNC_OTHER: ! 421: PS(hash_ops)->hash_update(hash_context, rbuf, toread); ! 422: break; ! 423: # endif /* HAVE_HASH_EXT */ ! 424: } ! 425: } ! 426: #else ! 427: int fd; ! 428: ! 429: fd = VCWD_OPEN(PS(entropy_file), O_RDONLY); ! 430: if (fd >= 0) { ! 431: unsigned char rbuf[2048]; ! 432: int n; ! 433: int to_read = PS(entropy_length); ! 434: ! 435: while (to_read > 0) { ! 436: n = read(fd, rbuf, MIN(to_read, sizeof(rbuf))); ! 437: if (n <= 0) break; ! 438: ! 439: switch (PS(hash_func)) { ! 440: case PS_HASH_FUNC_MD5: ! 441: PHP_MD5Update(&md5_context, rbuf, n); ! 442: break; ! 443: case PS_HASH_FUNC_SHA1: ! 444: PHP_SHA1Update(&sha1_context, rbuf, n); ! 445: break; ! 446: #if defined(HAVE_HASH_EXT) && !defined(COMPILE_DL_HASH) ! 447: case PS_HASH_FUNC_OTHER: ! 448: PS(hash_ops)->hash_update(hash_context, rbuf, n); ! 449: break; ! 450: #endif /* HAVE_HASH_EXT */ ! 451: } ! 452: to_read -= n; ! 453: } ! 454: close(fd); ! 455: } ! 456: #endif ! 457: } ! 458: ! 459: digest = emalloc(digest_len + 1); ! 460: switch (PS(hash_func)) { ! 461: case PS_HASH_FUNC_MD5: ! 462: PHP_MD5Final(digest, &md5_context); ! 463: break; ! 464: case PS_HASH_FUNC_SHA1: ! 465: PHP_SHA1Final(digest, &sha1_context); ! 466: break; ! 467: #if defined(HAVE_HASH_EXT) && !defined(COMPILE_DL_HASH) ! 468: case PS_HASH_FUNC_OTHER: ! 469: PS(hash_ops)->hash_final(digest, hash_context); ! 470: efree(hash_context); ! 471: break; ! 472: #endif /* HAVE_HASH_EXT */ ! 473: } ! 474: ! 475: if (PS(hash_bits_per_character) < 4 ! 476: || PS(hash_bits_per_character) > 6) { ! 477: PS(hash_bits_per_character) = 4; ! 478: ! 479: php_error_docref(NULL TSRMLS_CC, E_WARNING, "The ini setting hash_bits_per_character is out of range (should be 4, 5, or 6) - using 4 for now"); ! 480: } ! 481: ! 482: outid = emalloc((size_t)((digest_len + 2) * ((8.0f / PS(hash_bits_per_character)) + 0.5))); ! 483: j = (int) (bin_to_readable((char *)digest, digest_len, outid, (char)PS(hash_bits_per_character)) - outid); ! 484: efree(digest); ! 485: ! 486: if (newlen) { ! 487: *newlen = j; ! 488: } ! 489: ! 490: return outid; ! 491: } ! 492: /* }}} */ ! 493: ! 494: static void php_session_initialize(TSRMLS_D) /* {{{ */ ! 495: { ! 496: char *val; ! 497: int vallen; ! 498: ! 499: /* check session name for invalid characters */ ! 500: if (PS(id) && strpbrk(PS(id), "\r\n\t <>'\"\\")) { ! 501: efree(PS(id)); ! 502: PS(id) = NULL; ! 503: } ! 504: ! 505: if (!PS(mod)) { ! 506: php_error_docref(NULL TSRMLS_CC, E_ERROR, "No storage module chosen - failed to initialize session"); ! 507: return; ! 508: } ! 509: ! 510: /* Open session handler first */ ! 511: if (PS(mod)->s_open(&PS(mod_data), PS(save_path), PS(session_name) TSRMLS_CC) == FAILURE) { ! 512: php_error_docref(NULL TSRMLS_CC, E_ERROR, "Failed to initialize storage module: %s (path: %s)", PS(mod)->s_name, PS(save_path)); ! 513: return; ! 514: } ! 515: ! 516: /* If there is no ID, use session module to create one */ ! 517: if (!PS(id)) { ! 518: new_session: ! 519: PS(id) = PS(mod)->s_create_sid(&PS(mod_data), NULL TSRMLS_CC); ! 520: if (PS(use_cookies)) { ! 521: PS(send_cookie) = 1; ! 522: } ! 523: } ! 524: ! 525: /* Read data */ ! 526: /* Question: if you create a SID here, should you also try to read data? ! 527: * I'm not sure, but while not doing so will remove one session operation ! 528: * it could prove usefull for those sites which wish to have "default" ! 529: * session information. */ ! 530: php_session_track_init(TSRMLS_C); ! 531: PS(invalid_session_id) = 0; ! 532: if (PS(mod)->s_read(&PS(mod_data), PS(id), &val, &vallen TSRMLS_CC) == SUCCESS) { ! 533: php_session_decode(val, vallen TSRMLS_CC); ! 534: efree(val); ! 535: } else if (PS(invalid_session_id)) { /* address instances where the session read fails due to an invalid id */ ! 536: PS(invalid_session_id) = 0; ! 537: efree(PS(id)); ! 538: PS(id) = NULL; ! 539: goto new_session; ! 540: } ! 541: } ! 542: /* }}} */ ! 543: ! 544: static int migrate_global(HashTable *ht, HashPosition *pos TSRMLS_DC) /* {{{ */ ! 545: { ! 546: char *str; ! 547: uint str_len; ! 548: ulong num_key; ! 549: int n; ! 550: zval **val; ! 551: int ret = 0; ! 552: ! 553: n = zend_hash_get_current_key_ex(ht, &str, &str_len, &num_key, 0, pos); ! 554: ! 555: switch (n) { ! 556: case HASH_KEY_IS_STRING: ! 557: if (zend_hash_find(&EG(symbol_table), str, str_len, (void **) &val) == SUCCESS && ! 558: val && Z_TYPE_PP(val) != IS_NULL ! 559: ) { ! 560: ZEND_SET_SYMBOL_WITH_LENGTH(ht, str, str_len, *val, Z_REFCOUNT_PP(val) + 1, 1); ! 561: ret = 1; ! 562: } ! 563: break; ! 564: case HASH_KEY_IS_LONG: ! 565: php_error_docref(NULL TSRMLS_CC, E_NOTICE, "The session bug compatibility code will not " ! 566: "try to locate the global variable $%lu due to its " ! 567: "numeric nature", num_key); ! 568: break; ! 569: } ! 570: return ret; ! 571: } ! 572: /* }}} */ ! 573: ! 574: static void php_session_save_current_state(TSRMLS_D) /* {{{ */ ! 575: { ! 576: int ret = FAILURE; ! 577: ! 578: IF_SESSION_VARS() { ! 579: if (PS(bug_compat) && !PG(register_globals)) { ! 580: HashTable *ht = Z_ARRVAL_P(PS(http_session_vars)); ! 581: HashPosition pos; ! 582: zval **val; ! 583: int do_warn = 0; ! 584: ! 585: zend_hash_internal_pointer_reset_ex(ht, &pos); ! 586: ! 587: while (zend_hash_get_current_data_ex(ht, (void **) &val, &pos) != FAILURE) { ! 588: if (Z_TYPE_PP(val) == IS_NULL) { ! 589: if (migrate_global(ht, &pos TSRMLS_CC)) { ! 590: do_warn = 1; ! 591: } ! 592: } ! 593: zend_hash_move_forward_ex(ht, &pos); ! 594: } ! 595: ! 596: if (do_warn && PS(bug_compat_warn)) { ! 597: php_error_docref(NULL TSRMLS_CC, E_WARNING, "Your script possibly relies on a session side-effect which existed until PHP 4.2.3. Please be advised that the session extension does not consider global variables as a source of data, unless register_globals is enabled. You can disable this functionality and this warning by setting session.bug_compat_42 or session.bug_compat_warn to off, respectively"); ! 598: } ! 599: } ! 600: ! 601: if (PS(mod_data)) { ! 602: char *val; ! 603: int vallen; ! 604: ! 605: val = php_session_encode(&vallen TSRMLS_CC); ! 606: if (val) { ! 607: ret = PS(mod)->s_write(&PS(mod_data), PS(id), val, vallen TSRMLS_CC); ! 608: efree(val); ! 609: } else { ! 610: ret = PS(mod)->s_write(&PS(mod_data), PS(id), "", 0 TSRMLS_CC); ! 611: } ! 612: } ! 613: ! 614: if (ret == FAILURE) { ! 615: php_error_docref(NULL TSRMLS_CC, E_WARNING, "Failed to write session data (%s). Please " ! 616: "verify that the current setting of session.save_path " ! 617: "is correct (%s)", ! 618: PS(mod)->s_name, ! 619: PS(save_path)); ! 620: } ! 621: } ! 622: ! 623: if (PS(mod_data)) { ! 624: PS(mod)->s_close(&PS(mod_data) TSRMLS_CC); ! 625: } ! 626: } ! 627: /* }}} */ ! 628: ! 629: /* ************************* ! 630: * INI Settings/Handlers * ! 631: ************************* */ ! 632: ! 633: static PHP_INI_MH(OnUpdateSaveHandler) /* {{{ */ ! 634: { ! 635: ps_module *tmp; ! 636: SESSION_CHECK_ACTIVE_STATE; ! 637: ! 638: tmp = _php_find_ps_module(new_value TSRMLS_CC); ! 639: ! 640: if (PG(modules_activated) && !tmp) { ! 641: int err_type; ! 642: ! 643: if (stage == ZEND_INI_STAGE_RUNTIME) { ! 644: err_type = E_WARNING; ! 645: } else { ! 646: err_type = E_ERROR; ! 647: } ! 648: ! 649: /* Do not output error when restoring ini options. */ ! 650: if (stage != ZEND_INI_STAGE_DEACTIVATE) { ! 651: php_error_docref(NULL TSRMLS_CC, err_type, "Cannot find save handler '%s'", new_value); ! 652: } ! 653: return FAILURE; ! 654: } ! 655: PS(mod) = tmp; ! 656: ! 657: return SUCCESS; ! 658: } ! 659: /* }}} */ ! 660: ! 661: static PHP_INI_MH(OnUpdateSerializer) /* {{{ */ ! 662: { ! 663: const ps_serializer *tmp; ! 664: SESSION_CHECK_ACTIVE_STATE; ! 665: ! 666: tmp = _php_find_ps_serializer(new_value TSRMLS_CC); ! 667: ! 668: if (PG(modules_activated) && !tmp) { ! 669: int err_type; ! 670: ! 671: if (stage == ZEND_INI_STAGE_RUNTIME) { ! 672: err_type = E_WARNING; ! 673: } else { ! 674: err_type = E_ERROR; ! 675: } ! 676: ! 677: /* Do not output error when restoring ini options. */ ! 678: if (stage != ZEND_INI_STAGE_DEACTIVATE) { ! 679: php_error_docref(NULL TSRMLS_CC, err_type, "Cannot find serialization handler '%s'", new_value); ! 680: } ! 681: return FAILURE; ! 682: } ! 683: PS(serializer) = tmp; ! 684: ! 685: return SUCCESS; ! 686: } ! 687: /* }}} */ ! 688: ! 689: static PHP_INI_MH(OnUpdateTransSid) /* {{{ */ ! 690: { ! 691: SESSION_CHECK_ACTIVE_STATE; ! 692: ! 693: if (!strncasecmp(new_value, "on", sizeof("on"))) { ! 694: PS(use_trans_sid) = (zend_bool) 1; ! 695: } else { ! 696: PS(use_trans_sid) = (zend_bool) atoi(new_value); ! 697: } ! 698: ! 699: return SUCCESS; ! 700: } ! 701: /* }}} */ ! 702: ! 703: static PHP_INI_MH(OnUpdateSaveDir) /* {{{ */ ! 704: { ! 705: /* Only do the safemode/open_basedir check at runtime */ ! 706: if (stage == PHP_INI_STAGE_RUNTIME || stage == PHP_INI_STAGE_HTACCESS) { ! 707: char *p; ! 708: ! 709: if (memchr(new_value, '\0', new_value_length) != NULL) { ! 710: return FAILURE; ! 711: } ! 712: ! 713: /* we do not use zend_memrchr() since path can contain ; itself */ ! 714: if ((p = strchr(new_value, ';'))) { ! 715: char *p2; ! 716: p++; ! 717: if ((p2 = strchr(p, ';'))) { ! 718: p = p2 + 1; ! 719: } ! 720: } else { ! 721: p = new_value; ! 722: } ! 723: ! 724: if (PG(safe_mode) && *p && (!php_checkuid(p, NULL, CHECKUID_CHECK_FILE_AND_DIR))) { ! 725: return FAILURE; ! 726: } ! 727: ! 728: if (PG(open_basedir) && *p && php_check_open_basedir(p TSRMLS_CC)) { ! 729: return FAILURE; ! 730: } ! 731: } ! 732: ! 733: OnUpdateString(entry, new_value, new_value_length, mh_arg1, mh_arg2, mh_arg3, stage TSRMLS_CC); ! 734: return SUCCESS; ! 735: } ! 736: /* }}} */ ! 737: ! 738: static PHP_INI_MH(OnUpdateHashFunc) /* {{{ */ ! 739: { ! 740: long val; ! 741: char *endptr = NULL; ! 742: ! 743: #if defined(HAVE_HASH_EXT) && !defined(COMPILE_DL_HASH) ! 744: PS(hash_ops) = NULL; ! 745: #endif ! 746: ! 747: val = strtol(new_value, &endptr, 10); ! 748: if (endptr && (*endptr == '\0')) { ! 749: /* Numeric value */ ! 750: PS(hash_func) = val ? 1 : 0; ! 751: ! 752: return SUCCESS; ! 753: } ! 754: ! 755: if (new_value_length == (sizeof("md5") - 1) && ! 756: strncasecmp(new_value, "md5", sizeof("md5") - 1) == 0) { ! 757: PS(hash_func) = PS_HASH_FUNC_MD5; ! 758: ! 759: return SUCCESS; ! 760: } ! 761: ! 762: if (new_value_length == (sizeof("sha1") - 1) && ! 763: strncasecmp(new_value, "sha1", sizeof("sha1") - 1) == 0) { ! 764: PS(hash_func) = PS_HASH_FUNC_SHA1; ! 765: ! 766: return SUCCESS; ! 767: } ! 768: ! 769: #if defined(HAVE_HASH_EXT) && !defined(COMPILE_DL_HASH) /* {{{ */ ! 770: { ! 771: php_hash_ops *ops = (php_hash_ops*)php_hash_fetch_ops(new_value, new_value_length); ! 772: ! 773: if (ops) { ! 774: PS(hash_func) = PS_HASH_FUNC_OTHER; ! 775: PS(hash_ops) = ops; ! 776: ! 777: return SUCCESS; ! 778: } ! 779: } ! 780: #endif /* HAVE_HASH_EXT }}} */ ! 781: ! 782: return FAILURE; ! 783: } ! 784: /* }}} */ ! 785: ! 786: /* {{{ PHP_INI ! 787: */ ! 788: PHP_INI_BEGIN() ! 789: STD_PHP_INI_BOOLEAN("session.bug_compat_42", "1", PHP_INI_ALL, OnUpdateBool, bug_compat, php_ps_globals, ps_globals) ! 790: STD_PHP_INI_BOOLEAN("session.bug_compat_warn", "1", PHP_INI_ALL, OnUpdateBool, bug_compat_warn, php_ps_globals, ps_globals) ! 791: STD_PHP_INI_ENTRY("session.save_path", "", PHP_INI_ALL, OnUpdateSaveDir,save_path, php_ps_globals, ps_globals) ! 792: STD_PHP_INI_ENTRY("session.name", "PHPSESSID", PHP_INI_ALL, OnUpdateString, session_name, php_ps_globals, ps_globals) ! 793: PHP_INI_ENTRY("session.save_handler", "files", PHP_INI_ALL, OnUpdateSaveHandler) ! 794: STD_PHP_INI_BOOLEAN("session.auto_start", "0", PHP_INI_ALL, OnUpdateBool, auto_start, php_ps_globals, ps_globals) ! 795: STD_PHP_INI_ENTRY("session.gc_probability", "1", PHP_INI_ALL, OnUpdateLong, gc_probability, php_ps_globals, ps_globals) ! 796: STD_PHP_INI_ENTRY("session.gc_divisor", "100", PHP_INI_ALL, OnUpdateLong, gc_divisor, php_ps_globals, ps_globals) ! 797: STD_PHP_INI_ENTRY("session.gc_maxlifetime", "1440", PHP_INI_ALL, OnUpdateLong, gc_maxlifetime, php_ps_globals, ps_globals) ! 798: PHP_INI_ENTRY("session.serialize_handler", "php", PHP_INI_ALL, OnUpdateSerializer) ! 799: STD_PHP_INI_ENTRY("session.cookie_lifetime", "0", PHP_INI_ALL, OnUpdateLong, cookie_lifetime, php_ps_globals, ps_globals) ! 800: STD_PHP_INI_ENTRY("session.cookie_path", "/", PHP_INI_ALL, OnUpdateString, cookie_path, php_ps_globals, ps_globals) ! 801: STD_PHP_INI_ENTRY("session.cookie_domain", "", PHP_INI_ALL, OnUpdateString, cookie_domain, php_ps_globals, ps_globals) ! 802: STD_PHP_INI_BOOLEAN("session.cookie_secure", "", PHP_INI_ALL, OnUpdateBool, cookie_secure, php_ps_globals, ps_globals) ! 803: STD_PHP_INI_BOOLEAN("session.cookie_httponly", "", PHP_INI_ALL, OnUpdateBool, cookie_httponly, php_ps_globals, ps_globals) ! 804: STD_PHP_INI_BOOLEAN("session.use_cookies", "1", PHP_INI_ALL, OnUpdateBool, use_cookies, php_ps_globals, ps_globals) ! 805: STD_PHP_INI_BOOLEAN("session.use_only_cookies", "1", PHP_INI_ALL, OnUpdateBool, use_only_cookies, php_ps_globals, ps_globals) ! 806: STD_PHP_INI_ENTRY("session.referer_check", "", PHP_INI_ALL, OnUpdateString, extern_referer_chk, php_ps_globals, ps_globals) ! 807: STD_PHP_INI_ENTRY("session.entropy_file", "", PHP_INI_ALL, OnUpdateString, entropy_file, php_ps_globals, ps_globals) ! 808: STD_PHP_INI_ENTRY("session.entropy_length", "0", PHP_INI_ALL, OnUpdateLong, entropy_length, php_ps_globals, ps_globals) ! 809: STD_PHP_INI_ENTRY("session.cache_limiter", "nocache", PHP_INI_ALL, OnUpdateString, cache_limiter, php_ps_globals, ps_globals) ! 810: STD_PHP_INI_ENTRY("session.cache_expire", "180", PHP_INI_ALL, OnUpdateLong, cache_expire, php_ps_globals, ps_globals) ! 811: PHP_INI_ENTRY("session.use_trans_sid", "0", PHP_INI_ALL, OnUpdateTransSid) ! 812: PHP_INI_ENTRY("session.hash_function", "0", PHP_INI_ALL, OnUpdateHashFunc) ! 813: STD_PHP_INI_ENTRY("session.hash_bits_per_character", "4", PHP_INI_ALL, OnUpdateLong, hash_bits_per_character, php_ps_globals, ps_globals) ! 814: ! 815: /* Commented out until future discussion */ ! 816: /* PHP_INI_ENTRY("session.encode_sources", "globals,track", PHP_INI_ALL, NULL) */ ! 817: PHP_INI_END() ! 818: /* }}} */ ! 819: ! 820: /* *************** ! 821: * Serializers * ! 822: *************** */ ! 823: ! 824: #define PS_BIN_NR_OF_BITS 8 ! 825: #define PS_BIN_UNDEF (1<<(PS_BIN_NR_OF_BITS-1)) ! 826: #define PS_BIN_MAX (PS_BIN_UNDEF-1) ! 827: ! 828: PS_SERIALIZER_ENCODE_FUNC(php_binary) /* {{{ */ ! 829: { ! 830: smart_str buf = {0}; ! 831: php_serialize_data_t var_hash; ! 832: PS_ENCODE_VARS; ! 833: ! 834: PHP_VAR_SERIALIZE_INIT(var_hash); ! 835: ! 836: PS_ENCODE_LOOP( ! 837: if (key_length > PS_BIN_MAX) continue; ! 838: smart_str_appendc(&buf, (unsigned char) key_length); ! 839: smart_str_appendl(&buf, key, key_length); ! 840: php_var_serialize(&buf, struc, &var_hash TSRMLS_CC); ! 841: } else { ! 842: if (key_length > PS_BIN_MAX) continue; ! 843: smart_str_appendc(&buf, (unsigned char) (key_length & PS_BIN_UNDEF)); ! 844: smart_str_appendl(&buf, key, key_length); ! 845: ); ! 846: ! 847: if (newlen) { ! 848: *newlen = buf.len; ! 849: } ! 850: smart_str_0(&buf); ! 851: *newstr = buf.c; ! 852: PHP_VAR_SERIALIZE_DESTROY(var_hash); ! 853: ! 854: return SUCCESS; ! 855: } ! 856: /* }}} */ ! 857: ! 858: PS_SERIALIZER_DECODE_FUNC(php_binary) /* {{{ */ ! 859: { ! 860: const char *p; ! 861: char *name; ! 862: const char *endptr = val + vallen; ! 863: zval *current; ! 864: int namelen; ! 865: int has_value; ! 866: php_unserialize_data_t var_hash; ! 867: ! 868: PHP_VAR_UNSERIALIZE_INIT(var_hash); ! 869: ! 870: for (p = val; p < endptr; ) { ! 871: zval **tmp; ! 872: namelen = ((unsigned char)(*p)) & (~PS_BIN_UNDEF); ! 873: ! 874: if (namelen < 0 || namelen > PS_BIN_MAX || (p + namelen) >= endptr) { ! 875: return FAILURE; ! 876: } ! 877: ! 878: has_value = *p & PS_BIN_UNDEF ? 0 : 1; ! 879: ! 880: name = estrndup(p + 1, namelen); ! 881: ! 882: p += namelen + 1; ! 883: ! 884: if (zend_hash_find(&EG(symbol_table), name, namelen + 1, (void **) &tmp) == SUCCESS) { ! 885: if ((Z_TYPE_PP(tmp) == IS_ARRAY && Z_ARRVAL_PP(tmp) == &EG(symbol_table)) || *tmp == PS(http_session_vars)) { ! 886: efree(name); ! 887: continue; ! 888: } ! 889: } ! 890: ! 891: if (has_value) { ! 892: ALLOC_INIT_ZVAL(current); ! 893: if (php_var_unserialize(¤t, (const unsigned char **) &p, (const unsigned char *) endptr, &var_hash TSRMLS_CC)) { ! 894: php_set_session_var(name, namelen, current, &var_hash TSRMLS_CC); ! 895: } ! 896: zval_ptr_dtor(¤t); ! 897: } ! 898: PS_ADD_VARL(name, namelen); ! 899: efree(name); ! 900: } ! 901: ! 902: PHP_VAR_UNSERIALIZE_DESTROY(var_hash); ! 903: ! 904: return SUCCESS; ! 905: } ! 906: /* }}} */ ! 907: ! 908: #define PS_DELIMITER '|' ! 909: #define PS_UNDEF_MARKER '!' ! 910: ! 911: PS_SERIALIZER_ENCODE_FUNC(php) /* {{{ */ ! 912: { ! 913: smart_str buf = {0}; ! 914: php_serialize_data_t var_hash; ! 915: PS_ENCODE_VARS; ! 916: ! 917: PHP_VAR_SERIALIZE_INIT(var_hash); ! 918: ! 919: PS_ENCODE_LOOP( ! 920: smart_str_appendl(&buf, key, key_length); ! 921: if (memchr(key, PS_DELIMITER, key_length) || memchr(key, PS_UNDEF_MARKER, key_length)) { ! 922: PHP_VAR_SERIALIZE_DESTROY(var_hash); ! 923: smart_str_free(&buf); ! 924: return FAILURE; ! 925: } ! 926: smart_str_appendc(&buf, PS_DELIMITER); ! 927: ! 928: php_var_serialize(&buf, struc, &var_hash TSRMLS_CC); ! 929: } else { ! 930: smart_str_appendc(&buf, PS_UNDEF_MARKER); ! 931: smart_str_appendl(&buf, key, key_length); ! 932: smart_str_appendc(&buf, PS_DELIMITER); ! 933: ); ! 934: ! 935: if (newlen) { ! 936: *newlen = buf.len; ! 937: } ! 938: smart_str_0(&buf); ! 939: *newstr = buf.c; ! 940: ! 941: PHP_VAR_SERIALIZE_DESTROY(var_hash); ! 942: return SUCCESS; ! 943: } ! 944: /* }}} */ ! 945: ! 946: PS_SERIALIZER_DECODE_FUNC(php) /* {{{ */ ! 947: { ! 948: const char *p, *q; ! 949: char *name; ! 950: const char *endptr = val + vallen; ! 951: zval *current; ! 952: int namelen; ! 953: int has_value; ! 954: php_unserialize_data_t var_hash; ! 955: ! 956: PHP_VAR_UNSERIALIZE_INIT(var_hash); ! 957: ! 958: p = val; ! 959: ! 960: while (p < endptr) { ! 961: zval **tmp; ! 962: q = p; ! 963: while (*q != PS_DELIMITER) { ! 964: if (++q >= endptr) goto break_outer_loop; ! 965: } ! 966: if (p[0] == PS_UNDEF_MARKER) { ! 967: p++; ! 968: has_value = 0; ! 969: } else { ! 970: has_value = 1; ! 971: } ! 972: ! 973: namelen = q - p; ! 974: name = estrndup(p, namelen); ! 975: q++; ! 976: ! 977: if (zend_hash_find(&EG(symbol_table), name, namelen + 1, (void **) &tmp) == SUCCESS) { ! 978: if ((Z_TYPE_PP(tmp) == IS_ARRAY && Z_ARRVAL_PP(tmp) == &EG(symbol_table)) || *tmp == PS(http_session_vars)) { ! 979: goto skip; ! 980: } ! 981: } ! 982: ! 983: if (has_value) { ! 984: ALLOC_INIT_ZVAL(current); ! 985: if (php_var_unserialize(¤t, (const unsigned char **) &q, (const unsigned char *) endptr, &var_hash TSRMLS_CC)) { ! 986: php_set_session_var(name, namelen, current, &var_hash TSRMLS_CC); ! 987: } ! 988: zval_ptr_dtor(¤t); ! 989: } ! 990: PS_ADD_VARL(name, namelen); ! 991: skip: ! 992: efree(name); ! 993: ! 994: p = q; ! 995: } ! 996: break_outer_loop: ! 997: ! 998: PHP_VAR_UNSERIALIZE_DESTROY(var_hash); ! 999: ! 1000: return SUCCESS; ! 1001: } ! 1002: /* }}} */ ! 1003: ! 1004: #define MAX_SERIALIZERS 10 ! 1005: #define PREDEFINED_SERIALIZERS 2 ! 1006: ! 1007: static ps_serializer ps_serializers[MAX_SERIALIZERS + 1] = { ! 1008: PS_SERIALIZER_ENTRY(php), ! 1009: PS_SERIALIZER_ENTRY(php_binary) ! 1010: }; ! 1011: ! 1012: PHPAPI int php_session_register_serializer(const char *name, int (*encode)(PS_SERIALIZER_ENCODE_ARGS), int (*decode)(PS_SERIALIZER_DECODE_ARGS)) /* {{{ */ ! 1013: { ! 1014: int ret = -1; ! 1015: int i; ! 1016: ! 1017: for (i = 0; i < MAX_SERIALIZERS; i++) { ! 1018: if (ps_serializers[i].name == NULL) { ! 1019: ps_serializers[i].name = name; ! 1020: ps_serializers[i].encode = encode; ! 1021: ps_serializers[i].decode = decode; ! 1022: ps_serializers[i + 1].name = NULL; ! 1023: ret = 0; ! 1024: break; ! 1025: } ! 1026: } ! 1027: return ret; ! 1028: } ! 1029: /* }}} */ ! 1030: ! 1031: /* ******************* ! 1032: * Storage Modules * ! 1033: ******************* */ ! 1034: ! 1035: #define MAX_MODULES 10 ! 1036: #define PREDEFINED_MODULES 2 ! 1037: ! 1038: static ps_module *ps_modules[MAX_MODULES + 1] = { ! 1039: ps_files_ptr, ! 1040: ps_user_ptr ! 1041: }; ! 1042: ! 1043: PHPAPI int php_session_register_module(ps_module *ptr) /* {{{ */ ! 1044: { ! 1045: int ret = -1; ! 1046: int i; ! 1047: ! 1048: for (i = 0; i < MAX_MODULES; i++) { ! 1049: if (!ps_modules[i]) { ! 1050: ps_modules[i] = ptr; ! 1051: ret = 0; ! 1052: break; ! 1053: } ! 1054: } ! 1055: return ret; ! 1056: } ! 1057: /* }}} */ ! 1058: ! 1059: /* ****************** ! 1060: * Cache Limiters * ! 1061: ****************** */ ! 1062: ! 1063: typedef struct { ! 1064: char *name; ! 1065: void (*func)(TSRMLS_D); ! 1066: } php_session_cache_limiter_t; ! 1067: ! 1068: #define CACHE_LIMITER(name) _php_cache_limiter_##name ! 1069: #define CACHE_LIMITER_FUNC(name) static void CACHE_LIMITER(name)(TSRMLS_D) ! 1070: #define CACHE_LIMITER_ENTRY(name) { #name, CACHE_LIMITER(name) }, ! 1071: #define ADD_HEADER(a) sapi_add_header(a, strlen(a), 1); ! 1072: #define MAX_STR 512 ! 1073: ! 1074: static char *month_names[] = { ! 1075: "Jan", "Feb", "Mar", "Apr", "May", "Jun", ! 1076: "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" ! 1077: }; ! 1078: ! 1079: static char *week_days[] = { ! 1080: "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun" ! 1081: }; ! 1082: ! 1083: static inline void strcpy_gmt(char *ubuf, time_t *when) /* {{{ */ ! 1084: { ! 1085: char buf[MAX_STR]; ! 1086: struct tm tm, *res; ! 1087: int n; ! 1088: ! 1089: res = php_gmtime_r(when, &tm); ! 1090: ! 1091: if (!res) { ! 1092: buf[0] = '\0'; ! 1093: return; ! 1094: } ! 1095: ! 1096: n = slprintf(buf, sizeof(buf), "%s, %02d %s %d %02d:%02d:%02d GMT", /* SAFE */ ! 1097: week_days[tm.tm_wday], tm.tm_mday, ! 1098: month_names[tm.tm_mon], tm.tm_year + 1900, ! 1099: tm.tm_hour, tm.tm_min, ! 1100: tm.tm_sec); ! 1101: memcpy(ubuf, buf, n); ! 1102: ubuf[n] = '\0'; ! 1103: } ! 1104: /* }}} */ ! 1105: ! 1106: static inline void last_modified(TSRMLS_D) /* {{{ */ ! 1107: { ! 1108: const char *path; ! 1109: struct stat sb; ! 1110: char buf[MAX_STR + 1]; ! 1111: ! 1112: path = SG(request_info).path_translated; ! 1113: if (path) { ! 1114: if (VCWD_STAT(path, &sb) == -1) { ! 1115: return; ! 1116: } ! 1117: ! 1118: #define LAST_MODIFIED "Last-Modified: " ! 1119: memcpy(buf, LAST_MODIFIED, sizeof(LAST_MODIFIED) - 1); ! 1120: strcpy_gmt(buf + sizeof(LAST_MODIFIED) - 1, &sb.st_mtime); ! 1121: ADD_HEADER(buf); ! 1122: } ! 1123: } ! 1124: /* }}} */ ! 1125: ! 1126: #define EXPIRES "Expires: " ! 1127: CACHE_LIMITER_FUNC(public) /* {{{ */ ! 1128: { ! 1129: char buf[MAX_STR + 1]; ! 1130: struct timeval tv; ! 1131: time_t now; ! 1132: ! 1133: gettimeofday(&tv, NULL); ! 1134: now = tv.tv_sec + PS(cache_expire) * 60; ! 1135: memcpy(buf, EXPIRES, sizeof(EXPIRES) - 1); ! 1136: strcpy_gmt(buf + sizeof(EXPIRES) - 1, &now); ! 1137: ADD_HEADER(buf); ! 1138: ! 1139: snprintf(buf, sizeof(buf) , "Cache-Control: public, max-age=%ld", PS(cache_expire) * 60); /* SAFE */ ! 1140: ADD_HEADER(buf); ! 1141: ! 1142: last_modified(TSRMLS_C); ! 1143: } ! 1144: /* }}} */ ! 1145: ! 1146: CACHE_LIMITER_FUNC(private_no_expire) /* {{{ */ ! 1147: { ! 1148: char buf[MAX_STR + 1]; ! 1149: ! 1150: snprintf(buf, sizeof(buf), "Cache-Control: private, max-age=%ld, pre-check=%ld", PS(cache_expire) * 60, PS(cache_expire) * 60); /* SAFE */ ! 1151: ADD_HEADER(buf); ! 1152: ! 1153: last_modified(TSRMLS_C); ! 1154: } ! 1155: /* }}} */ ! 1156: ! 1157: CACHE_LIMITER_FUNC(private) /* {{{ */ ! 1158: { ! 1159: ADD_HEADER("Expires: Thu, 19 Nov 1981 08:52:00 GMT"); ! 1160: CACHE_LIMITER(private_no_expire)(TSRMLS_C); ! 1161: } ! 1162: /* }}} */ ! 1163: ! 1164: CACHE_LIMITER_FUNC(nocache) /* {{{ */ ! 1165: { ! 1166: ADD_HEADER("Expires: Thu, 19 Nov 1981 08:52:00 GMT"); ! 1167: ! 1168: /* For HTTP/1.1 conforming clients and the rest (MSIE 5) */ ! 1169: ADD_HEADER("Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0"); ! 1170: ! 1171: /* For HTTP/1.0 conforming clients */ ! 1172: ADD_HEADER("Pragma: no-cache"); ! 1173: } ! 1174: /* }}} */ ! 1175: ! 1176: static php_session_cache_limiter_t php_session_cache_limiters[] = { ! 1177: CACHE_LIMITER_ENTRY(public) ! 1178: CACHE_LIMITER_ENTRY(private) ! 1179: CACHE_LIMITER_ENTRY(private_no_expire) ! 1180: CACHE_LIMITER_ENTRY(nocache) ! 1181: {0} ! 1182: }; ! 1183: ! 1184: static int php_session_cache_limiter(TSRMLS_D) /* {{{ */ ! 1185: { ! 1186: php_session_cache_limiter_t *lim; ! 1187: ! 1188: if (PS(cache_limiter)[0] == '\0') return 0; ! 1189: ! 1190: if (SG(headers_sent)) { ! 1191: char *output_start_filename = php_get_output_start_filename(TSRMLS_C); ! 1192: int output_start_lineno = php_get_output_start_lineno(TSRMLS_C); ! 1193: ! 1194: if (output_start_filename) { ! 1195: php_error_docref(NULL TSRMLS_CC, E_WARNING, "Cannot send session cache limiter - headers already sent (output started at %s:%d)", output_start_filename, output_start_lineno); ! 1196: } else { ! 1197: php_error_docref(NULL TSRMLS_CC, E_WARNING, "Cannot send session cache limiter - headers already sent"); ! 1198: } ! 1199: return -2; ! 1200: } ! 1201: ! 1202: for (lim = php_session_cache_limiters; lim->name; lim++) { ! 1203: if (!strcasecmp(lim->name, PS(cache_limiter))) { ! 1204: lim->func(TSRMLS_C); ! 1205: return 0; ! 1206: } ! 1207: } ! 1208: ! 1209: return -1; ! 1210: } ! 1211: /* }}} */ ! 1212: ! 1213: /* ********************* ! 1214: * Cookie Management * ! 1215: ********************* */ ! 1216: ! 1217: #define COOKIE_SET_COOKIE "Set-Cookie: " ! 1218: #define COOKIE_EXPIRES "; expires=" ! 1219: #define COOKIE_PATH "; path=" ! 1220: #define COOKIE_DOMAIN "; domain=" ! 1221: #define COOKIE_SECURE "; secure" ! 1222: #define COOKIE_HTTPONLY "; HttpOnly" ! 1223: ! 1224: static void php_session_send_cookie(TSRMLS_D) /* {{{ */ ! 1225: { ! 1226: smart_str ncookie = {0}; ! 1227: char *date_fmt = NULL; ! 1228: char *e_session_name, *e_id; ! 1229: ! 1230: if (SG(headers_sent)) { ! 1231: char *output_start_filename = php_get_output_start_filename(TSRMLS_C); ! 1232: int output_start_lineno = php_get_output_start_lineno(TSRMLS_C); ! 1233: ! 1234: if (output_start_filename) { ! 1235: php_error_docref(NULL TSRMLS_CC, E_WARNING, "Cannot send session cookie - headers already sent by (output started at %s:%d)", output_start_filename, output_start_lineno); ! 1236: } else { ! 1237: php_error_docref(NULL TSRMLS_CC, E_WARNING, "Cannot send session cookie - headers already sent"); ! 1238: } ! 1239: return; ! 1240: } ! 1241: ! 1242: /* URL encode session_name and id because they might be user supplied */ ! 1243: e_session_name = php_url_encode(PS(session_name), strlen(PS(session_name)), NULL); ! 1244: e_id = php_url_encode(PS(id), strlen(PS(id)), NULL); ! 1245: ! 1246: smart_str_appends(&ncookie, COOKIE_SET_COOKIE); ! 1247: smart_str_appends(&ncookie, e_session_name); ! 1248: smart_str_appendc(&ncookie, '='); ! 1249: smart_str_appends(&ncookie, e_id); ! 1250: ! 1251: efree(e_session_name); ! 1252: efree(e_id); ! 1253: ! 1254: if (PS(cookie_lifetime) > 0) { ! 1255: struct timeval tv; ! 1256: time_t t; ! 1257: ! 1258: gettimeofday(&tv, NULL); ! 1259: t = tv.tv_sec + PS(cookie_lifetime); ! 1260: ! 1261: if (t > 0) { ! 1262: date_fmt = php_format_date("D, d-M-Y H:i:s T", sizeof("D, d-M-Y H:i:s T")-1, t, 0 TSRMLS_CC); ! 1263: smart_str_appends(&ncookie, COOKIE_EXPIRES); ! 1264: smart_str_appends(&ncookie, date_fmt); ! 1265: efree(date_fmt); ! 1266: } ! 1267: } ! 1268: ! 1269: if (PS(cookie_path)[0]) { ! 1270: smart_str_appends(&ncookie, COOKIE_PATH); ! 1271: smart_str_appends(&ncookie, PS(cookie_path)); ! 1272: } ! 1273: ! 1274: if (PS(cookie_domain)[0]) { ! 1275: smart_str_appends(&ncookie, COOKIE_DOMAIN); ! 1276: smart_str_appends(&ncookie, PS(cookie_domain)); ! 1277: } ! 1278: ! 1279: if (PS(cookie_secure)) { ! 1280: smart_str_appends(&ncookie, COOKIE_SECURE); ! 1281: } ! 1282: ! 1283: if (PS(cookie_httponly)) { ! 1284: smart_str_appends(&ncookie, COOKIE_HTTPONLY); ! 1285: } ! 1286: ! 1287: smart_str_0(&ncookie); ! 1288: ! 1289: /* 'replace' must be 0 here, else a previous Set-Cookie ! 1290: header, probably sent with setcookie() will be replaced! */ ! 1291: sapi_add_header_ex(ncookie.c, ncookie.len, 0, 0 TSRMLS_CC); ! 1292: } ! 1293: /* }}} */ ! 1294: ! 1295: PHPAPI ps_module *_php_find_ps_module(char *name TSRMLS_DC) /* {{{ */ ! 1296: { ! 1297: ps_module *ret = NULL; ! 1298: ps_module **mod; ! 1299: int i; ! 1300: ! 1301: for (i = 0, mod = ps_modules; i < MAX_MODULES; i++, mod++) { ! 1302: if (*mod && !strcasecmp(name, (*mod)->s_name)) { ! 1303: ret = *mod; ! 1304: break; ! 1305: } ! 1306: } ! 1307: return ret; ! 1308: } ! 1309: /* }}} */ ! 1310: ! 1311: PHPAPI const ps_serializer *_php_find_ps_serializer(char *name TSRMLS_DC) /* {{{ */ ! 1312: { ! 1313: const ps_serializer *ret = NULL; ! 1314: const ps_serializer *mod; ! 1315: ! 1316: for (mod = ps_serializers; mod->name; mod++) { ! 1317: if (!strcasecmp(name, mod->name)) { ! 1318: ret = mod; ! 1319: break; ! 1320: } ! 1321: } ! 1322: return ret; ! 1323: } ! 1324: /* }}} */ ! 1325: ! 1326: #define PPID2SID \ ! 1327: convert_to_string((*ppid)); \ ! 1328: PS(id) = estrndup(Z_STRVAL_PP(ppid), Z_STRLEN_PP(ppid)) ! 1329: ! 1330: static void php_session_reset_id(TSRMLS_D) /* {{{ */ ! 1331: { ! 1332: int module_number = PS(module_number); ! 1333: ! 1334: if (PS(use_cookies) && PS(send_cookie)) { ! 1335: php_session_send_cookie(TSRMLS_C); ! 1336: PS(send_cookie) = 0; ! 1337: } ! 1338: ! 1339: /* if the SID constant exists, destroy it. */ ! 1340: zend_hash_del(EG(zend_constants), "sid", sizeof("sid")); ! 1341: ! 1342: if (PS(define_sid)) { ! 1343: smart_str var = {0}; ! 1344: ! 1345: smart_str_appends(&var, PS(session_name)); ! 1346: smart_str_appendc(&var, '='); ! 1347: smart_str_appends(&var, PS(id)); ! 1348: smart_str_0(&var); ! 1349: REGISTER_STRINGL_CONSTANT("SID", var.c, var.len, 0); ! 1350: } else { ! 1351: REGISTER_STRINGL_CONSTANT("SID", STR_EMPTY_ALLOC(), 0, 0); ! 1352: } ! 1353: ! 1354: if (PS(apply_trans_sid)) { ! 1355: php_url_scanner_reset_vars(TSRMLS_C); ! 1356: php_url_scanner_add_var(PS(session_name), strlen(PS(session_name)), PS(id), strlen(PS(id)), 1 TSRMLS_CC); ! 1357: } ! 1358: } ! 1359: /* }}} */ ! 1360: ! 1361: PHPAPI void php_session_start(TSRMLS_D) /* {{{ */ ! 1362: { ! 1363: zval **ppid; ! 1364: zval **data; ! 1365: char *p, *value; ! 1366: int nrand; ! 1367: int lensess; ! 1368: ! 1369: if (PS(use_only_cookies)) { ! 1370: PS(apply_trans_sid) = 0; ! 1371: } else { ! 1372: PS(apply_trans_sid) = PS(use_trans_sid); ! 1373: } ! 1374: ! 1375: switch (PS(session_status)) { ! 1376: case php_session_active: ! 1377: php_error(E_NOTICE, "A session had already been started - ignoring session_start()"); ! 1378: return; ! 1379: break; ! 1380: ! 1381: case php_session_disabled: ! 1382: value = zend_ini_string("session.save_handler", sizeof("session.save_handler"), 0); ! 1383: if (!PS(mod) && value) { ! 1384: PS(mod) = _php_find_ps_module(value TSRMLS_CC); ! 1385: if (!PS(mod)) { ! 1386: php_error_docref(NULL TSRMLS_CC, E_WARNING, "Cannot find save handler '%s' - session startup failed", value); ! 1387: return; ! 1388: } ! 1389: } ! 1390: value = zend_ini_string("session.serialize_handler", sizeof("session.serialize_handler"), 0); ! 1391: if (!PS(serializer) && value) { ! 1392: PS(serializer) = _php_find_ps_serializer(value TSRMLS_CC); ! 1393: if (!PS(serializer)) { ! 1394: php_error_docref(NULL TSRMLS_CC, E_WARNING, "Cannot find serialization handler '%s' - session startup failed", value); ! 1395: return; ! 1396: } ! 1397: } ! 1398: PS(session_status) = php_session_none; ! 1399: /* fallthrough */ ! 1400: ! 1401: default: ! 1402: case php_session_none: ! 1403: PS(define_sid) = 1; ! 1404: PS(send_cookie) = 1; ! 1405: } ! 1406: ! 1407: lensess = strlen(PS(session_name)); ! 1408: ! 1409: /* Cookies are preferred, because initially ! 1410: * cookie and get variables will be available. */ ! 1411: ! 1412: if (!PS(id)) { ! 1413: if (PS(use_cookies) && zend_hash_find(&EG(symbol_table), "_COOKIE", sizeof("_COOKIE"), (void **) &data) == SUCCESS && ! 1414: Z_TYPE_PP(data) == IS_ARRAY && ! 1415: zend_hash_find(Z_ARRVAL_PP(data), PS(session_name), lensess + 1, (void **) &ppid) == SUCCESS ! 1416: ) { ! 1417: PPID2SID; ! 1418: PS(apply_trans_sid) = 0; ! 1419: PS(send_cookie) = 0; ! 1420: PS(define_sid) = 0; ! 1421: } ! 1422: ! 1423: if (!PS(use_only_cookies) && !PS(id) && ! 1424: zend_hash_find(&EG(symbol_table), "_GET", sizeof("_GET"), (void **) &data) == SUCCESS && ! 1425: Z_TYPE_PP(data) == IS_ARRAY && ! 1426: zend_hash_find(Z_ARRVAL_PP(data), PS(session_name), lensess + 1, (void **) &ppid) == SUCCESS ! 1427: ) { ! 1428: PPID2SID; ! 1429: PS(send_cookie) = 0; ! 1430: } ! 1431: ! 1432: if (!PS(use_only_cookies) && !PS(id) && ! 1433: zend_hash_find(&EG(symbol_table), "_POST", sizeof("_POST"), (void **) &data) == SUCCESS && ! 1434: Z_TYPE_PP(data) == IS_ARRAY && ! 1435: zend_hash_find(Z_ARRVAL_PP(data), PS(session_name), lensess + 1, (void **) &ppid) == SUCCESS ! 1436: ) { ! 1437: PPID2SID; ! 1438: PS(send_cookie) = 0; ! 1439: } ! 1440: } ! 1441: ! 1442: /* Check the REQUEST_URI symbol for a string of the form ! 1443: * '<session-name>=<session-id>' to allow URLs of the form ! 1444: * http://yoursite/<session-name>=<session-id>/script.php */ ! 1445: ! 1446: if (!PS(use_only_cookies) && !PS(id) && PG(http_globals)[TRACK_VARS_SERVER] && ! 1447: zend_hash_find(Z_ARRVAL_P(PG(http_globals)[TRACK_VARS_SERVER]), "REQUEST_URI", sizeof("REQUEST_URI"), (void **) &data) == SUCCESS && ! 1448: Z_TYPE_PP(data) == IS_STRING && ! 1449: (p = strstr(Z_STRVAL_PP(data), PS(session_name))) && ! 1450: p[lensess] == '=' ! 1451: ) { ! 1452: char *q; ! 1453: ! 1454: p += lensess + 1; ! 1455: if ((q = strpbrk(p, "/?\\"))) { ! 1456: PS(id) = estrndup(p, q - p); ! 1457: PS(send_cookie) = 0; ! 1458: } ! 1459: } ! 1460: ! 1461: /* Check whether the current request was referred to by ! 1462: * an external site which invalidates the previously found id. */ ! 1463: ! 1464: if (PS(id) && ! 1465: PS(extern_referer_chk)[0] != '\0' && ! 1466: PG(http_globals)[TRACK_VARS_SERVER] && ! 1467: zend_hash_find(Z_ARRVAL_P(PG(http_globals)[TRACK_VARS_SERVER]), "HTTP_REFERER", sizeof("HTTP_REFERER"), (void **) &data) == SUCCESS && ! 1468: Z_TYPE_PP(data) == IS_STRING && ! 1469: Z_STRLEN_PP(data) != 0 && ! 1470: strstr(Z_STRVAL_PP(data), PS(extern_referer_chk)) == NULL ! 1471: ) { ! 1472: efree(PS(id)); ! 1473: PS(id) = NULL; ! 1474: PS(send_cookie) = 1; ! 1475: if (PS(use_trans_sid) && !PS(use_only_cookies)) { ! 1476: PS(apply_trans_sid) = 1; ! 1477: } ! 1478: } ! 1479: ! 1480: php_session_initialize(TSRMLS_C); ! 1481: ! 1482: if (!PS(use_cookies) && PS(send_cookie)) { ! 1483: if (PS(use_trans_sid) && !PS(use_only_cookies)) { ! 1484: PS(apply_trans_sid) = 1; ! 1485: } ! 1486: PS(send_cookie) = 0; ! 1487: } ! 1488: ! 1489: php_session_reset_id(TSRMLS_C); ! 1490: ! 1491: PS(session_status) = php_session_active; ! 1492: ! 1493: php_session_cache_limiter(TSRMLS_C); ! 1494: ! 1495: if (PS(mod_data) && PS(gc_probability) > 0) { ! 1496: int nrdels = -1; ! 1497: ! 1498: nrand = (int) ((float) PS(gc_divisor) * php_combined_lcg(TSRMLS_C)); ! 1499: if (nrand < PS(gc_probability)) { ! 1500: PS(mod)->s_gc(&PS(mod_data), PS(gc_maxlifetime), &nrdels TSRMLS_CC); ! 1501: #ifdef SESSION_DEBUG ! 1502: if (nrdels != -1) { ! 1503: php_error_docref(NULL TSRMLS_CC, E_NOTICE, "purged %d expired session objects", nrdels); ! 1504: } ! 1505: #endif ! 1506: } ! 1507: } ! 1508: } ! 1509: /* }}} */ ! 1510: ! 1511: static void php_session_flush(TSRMLS_D) /* {{{ */ ! 1512: { ! 1513: if (PS(session_status) == php_session_active) { ! 1514: PS(session_status) = php_session_none; ! 1515: zend_try { ! 1516: php_session_save_current_state(TSRMLS_C); ! 1517: } zend_end_try(); ! 1518: } ! 1519: } ! 1520: /* }}} */ ! 1521: ! 1522: PHPAPI void session_adapt_url(const char *url, size_t urllen, char **new, size_t *newlen TSRMLS_DC) /* {{{ */ ! 1523: { ! 1524: if (PS(apply_trans_sid) && (PS(session_status) == php_session_active)) { ! 1525: *new = php_url_scanner_adapt_single_url(url, urllen, PS(session_name), PS(id), newlen TSRMLS_CC); ! 1526: } ! 1527: } ! 1528: /* }}} */ ! 1529: ! 1530: /* ******************************** ! 1531: * Userspace exported functions * ! 1532: ******************************** */ ! 1533: ! 1534: /* {{{ proto void session_set_cookie_params(int lifetime [, string path [, string domain [, bool secure[, bool httponly]]]]) ! 1535: Set session cookie parameters */ ! 1536: static PHP_FUNCTION(session_set_cookie_params) ! 1537: { ! 1538: zval **lifetime = NULL; ! 1539: char *path = NULL, *domain = NULL; ! 1540: int path_len, domain_len, argc = ZEND_NUM_ARGS(); ! 1541: zend_bool secure = 0, httponly = 0; ! 1542: ! 1543: if (!PS(use_cookies) || ! 1544: zend_parse_parameters(argc TSRMLS_CC, "Z|ssbb", &lifetime, &path, &path_len, &domain, &domain_len, &secure, &httponly) == FAILURE) { ! 1545: return; ! 1546: } ! 1547: ! 1548: convert_to_string_ex(lifetime); ! 1549: ! 1550: zend_alter_ini_entry("session.cookie_lifetime", sizeof("session.cookie_lifetime"), Z_STRVAL_PP(lifetime), Z_STRLEN_PP(lifetime), PHP_INI_USER, PHP_INI_STAGE_RUNTIME); ! 1551: ! 1552: if (path) { ! 1553: zend_alter_ini_entry("session.cookie_path", sizeof("session.cookie_path"), path, path_len, PHP_INI_USER, PHP_INI_STAGE_RUNTIME); ! 1554: } ! 1555: if (domain) { ! 1556: zend_alter_ini_entry("session.cookie_domain", sizeof("session.cookie_domain"), domain, domain_len, PHP_INI_USER, PHP_INI_STAGE_RUNTIME); ! 1557: } ! 1558: ! 1559: if (argc > 3) { ! 1560: zend_alter_ini_entry("session.cookie_secure", sizeof("session.cookie_secure"), secure ? "1" : "0", 1, PHP_INI_USER, PHP_INI_STAGE_RUNTIME); ! 1561: } ! 1562: if (argc > 4) { ! 1563: zend_alter_ini_entry("session.cookie_httponly", sizeof("session.cookie_httponly"), httponly ? "1" : "0", 1, PHP_INI_USER, PHP_INI_STAGE_RUNTIME); ! 1564: } ! 1565: } ! 1566: /* }}} */ ! 1567: ! 1568: /* {{{ proto array session_get_cookie_params(void) ! 1569: Return the session cookie parameters */ ! 1570: static PHP_FUNCTION(session_get_cookie_params) ! 1571: { ! 1572: if (zend_parse_parameters_none() == FAILURE) { ! 1573: return; ! 1574: } ! 1575: ! 1576: array_init(return_value); ! 1577: ! 1578: add_assoc_long(return_value, "lifetime", PS(cookie_lifetime)); ! 1579: add_assoc_string(return_value, "path", PS(cookie_path), 1); ! 1580: add_assoc_string(return_value, "domain", PS(cookie_domain), 1); ! 1581: add_assoc_bool(return_value, "secure", PS(cookie_secure)); ! 1582: add_assoc_bool(return_value, "httponly", PS(cookie_httponly)); ! 1583: } ! 1584: /* }}} */ ! 1585: ! 1586: /* {{{ proto string session_name([string newname]) ! 1587: Return the current session name. If newname is given, the session name is replaced with newname */ ! 1588: static PHP_FUNCTION(session_name) ! 1589: { ! 1590: char *name = NULL; ! 1591: int name_len; ! 1592: ! 1593: if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|s", &name, &name_len) == FAILURE) { ! 1594: return; ! 1595: } ! 1596: ! 1597: RETVAL_STRING(PS(session_name), 1); ! 1598: ! 1599: if (name) { ! 1600: zend_alter_ini_entry("session.name", sizeof("session.name"), name, name_len, PHP_INI_USER, PHP_INI_STAGE_RUNTIME); ! 1601: } ! 1602: } ! 1603: /* }}} */ ! 1604: ! 1605: /* {{{ proto string session_module_name([string newname]) ! 1606: Return the current module name used for accessing session data. If newname is given, the module name is replaced with newname */ ! 1607: static PHP_FUNCTION(session_module_name) ! 1608: { ! 1609: char *name = NULL; ! 1610: int name_len; ! 1611: ! 1612: if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|s", &name, &name_len) == FAILURE) { ! 1613: return; ! 1614: } ! 1615: ! 1616: /* Set return_value to current module name */ ! 1617: if (PS(mod) && PS(mod)->s_name) { ! 1618: RETVAL_STRING(safe_estrdup(PS(mod)->s_name), 0); ! 1619: } else { ! 1620: RETVAL_EMPTY_STRING(); ! 1621: } ! 1622: ! 1623: if (name) { ! 1624: if (!_php_find_ps_module(name TSRMLS_CC)) { ! 1625: php_error_docref(NULL TSRMLS_CC, E_WARNING, "Cannot find named PHP session module (%s)", name); ! 1626: ! 1627: zval_dtor(return_value); ! 1628: RETURN_FALSE; ! 1629: } ! 1630: if (PS(mod_data)) { ! 1631: PS(mod)->s_close(&PS(mod_data) TSRMLS_CC); ! 1632: } ! 1633: PS(mod_data) = NULL; ! 1634: ! 1635: zend_alter_ini_entry("session.save_handler", sizeof("session.save_handler"), name, name_len, PHP_INI_USER, PHP_INI_STAGE_RUNTIME); ! 1636: } ! 1637: } ! 1638: /* }}} */ ! 1639: ! 1640: /* {{{ proto void session_set_save_handler(string open, string close, string read, string write, string destroy, string gc) ! 1641: Sets user-level functions */ ! 1642: static PHP_FUNCTION(session_set_save_handler) ! 1643: { ! 1644: zval ***args = NULL; ! 1645: int i, num_args, argc = ZEND_NUM_ARGS(); ! 1646: char *name; ! 1647: ! 1648: if (PS(session_status) != php_session_none) { ! 1649: RETURN_FALSE; ! 1650: } ! 1651: ! 1652: if (argc != 6) { ! 1653: WRONG_PARAM_COUNT; ! 1654: } ! 1655: ! 1656: if (zend_parse_parameters(argc TSRMLS_CC, "+", &args, &num_args) == FAILURE) { ! 1657: return; ! 1658: } ! 1659: ! 1660: for (i = 0; i < 6; i++) { ! 1661: if (!zend_is_callable(*args[i], 0, &name TSRMLS_CC)) { ! 1662: efree(args); ! 1663: php_error_docref(NULL TSRMLS_CC, E_WARNING, "Argument %d is not a valid callback", i+1); ! 1664: efree(name); ! 1665: RETURN_FALSE; ! 1666: } ! 1667: efree(name); ! 1668: } ! 1669: ! 1670: zend_alter_ini_entry("session.save_handler", sizeof("session.save_handler"), "user", sizeof("user")-1, PHP_INI_USER, PHP_INI_STAGE_RUNTIME); ! 1671: ! 1672: for (i = 0; i < 6; i++) { ! 1673: if (PS(mod_user_names).names[i] != NULL) { ! 1674: zval_ptr_dtor(&PS(mod_user_names).names[i]); ! 1675: } ! 1676: Z_ADDREF_PP(args[i]); ! 1677: PS(mod_user_names).names[i] = *args[i]; ! 1678: } ! 1679: ! 1680: efree(args); ! 1681: RETURN_TRUE; ! 1682: } ! 1683: /* }}} */ ! 1684: ! 1685: /* {{{ proto string session_save_path([string newname]) ! 1686: Return the current save path passed to module_name. If newname is given, the save path is replaced with newname */ ! 1687: static PHP_FUNCTION(session_save_path) ! 1688: { ! 1689: char *name = NULL; ! 1690: int name_len; ! 1691: ! 1692: if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|s", &name, &name_len) == FAILURE) { ! 1693: return; ! 1694: } ! 1695: ! 1696: RETVAL_STRING(PS(save_path), 1); ! 1697: ! 1698: if (name) { ! 1699: if (memchr(name, '\0', name_len) != NULL) { ! 1700: php_error_docref(NULL TSRMLS_CC, E_WARNING, "The save_path cannot contain NULL characters"); ! 1701: zval_dtor(return_value); ! 1702: RETURN_FALSE; ! 1703: } ! 1704: zend_alter_ini_entry("session.save_path", sizeof("session.save_path"), name, name_len, PHP_INI_USER, PHP_INI_STAGE_RUNTIME); ! 1705: } ! 1706: } ! 1707: /* }}} */ ! 1708: ! 1709: /* {{{ proto string session_id([string newid]) ! 1710: Return the current session id. If newid is given, the session id is replaced with newid */ ! 1711: static PHP_FUNCTION(session_id) ! 1712: { ! 1713: char *name = NULL; ! 1714: int name_len; ! 1715: ! 1716: if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|s", &name, &name_len) == FAILURE) { ! 1717: return; ! 1718: } ! 1719: ! 1720: if (PS(id)) { ! 1721: RETVAL_STRING(PS(id), 1); ! 1722: } else { ! 1723: RETVAL_EMPTY_STRING(); ! 1724: } ! 1725: ! 1726: if (name) { ! 1727: if (PS(id)) { ! 1728: efree(PS(id)); ! 1729: } ! 1730: PS(id) = estrndup(name, name_len); ! 1731: } ! 1732: } ! 1733: /* }}} */ ! 1734: ! 1735: /* {{{ proto bool session_regenerate_id([bool delete_old_session]) ! 1736: Update the current session id with a newly generated one. If delete_old_session is set to true, remove the old session. */ ! 1737: static PHP_FUNCTION(session_regenerate_id) ! 1738: { ! 1739: zend_bool del_ses = 0; ! 1740: ! 1741: if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|b", &del_ses) == FAILURE) { ! 1742: return; ! 1743: } ! 1744: ! 1745: if (SG(headers_sent) && PS(use_cookies)) { ! 1746: php_error_docref(NULL TSRMLS_CC, E_WARNING, "Cannot regenerate session id - headers already sent"); ! 1747: RETURN_FALSE; ! 1748: } ! 1749: ! 1750: if (PS(session_status) == php_session_active) { ! 1751: if (PS(id)) { ! 1752: if (del_ses && PS(mod)->s_destroy(&PS(mod_data), PS(id) TSRMLS_CC) == FAILURE) { ! 1753: php_error_docref(NULL TSRMLS_CC, E_WARNING, "Session object destruction failed"); ! 1754: RETURN_FALSE; ! 1755: } ! 1756: efree(PS(id)); ! 1757: PS(id) = NULL; ! 1758: } ! 1759: ! 1760: PS(id) = PS(mod)->s_create_sid(&PS(mod_data), NULL TSRMLS_CC); ! 1761: ! 1762: PS(send_cookie) = 1; ! 1763: php_session_reset_id(TSRMLS_C); ! 1764: ! 1765: RETURN_TRUE; ! 1766: } ! 1767: RETURN_FALSE; ! 1768: } ! 1769: /* }}} */ ! 1770: ! 1771: /* {{{ proto string session_cache_limiter([string new_cache_limiter]) ! 1772: Return the current cache limiter. If new_cache_limited is given, the current cache_limiter is replaced with new_cache_limiter */ ! 1773: static PHP_FUNCTION(session_cache_limiter) ! 1774: { ! 1775: char *limiter = NULL; ! 1776: int limiter_len; ! 1777: ! 1778: if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|s", &limiter, &limiter_len) == FAILURE) { ! 1779: return; ! 1780: } ! 1781: ! 1782: RETVAL_STRING(PS(cache_limiter), 1); ! 1783: ! 1784: if (limiter) { ! 1785: zend_alter_ini_entry("session.cache_limiter", sizeof("session.cache_limiter"), limiter, limiter_len, PHP_INI_USER, PHP_INI_STAGE_RUNTIME); ! 1786: } ! 1787: } ! 1788: /* }}} */ ! 1789: ! 1790: /* {{{ proto int session_cache_expire([int new_cache_expire]) ! 1791: Return the current cache expire. If new_cache_expire is given, the current cache_expire is replaced with new_cache_expire */ ! 1792: static PHP_FUNCTION(session_cache_expire) ! 1793: { ! 1794: zval **expires = NULL; ! 1795: int argc = ZEND_NUM_ARGS(); ! 1796: ! 1797: if (zend_parse_parameters(argc TSRMLS_CC, "|Z", &expires) == FAILURE) { ! 1798: return; ! 1799: } ! 1800: ! 1801: RETVAL_LONG(PS(cache_expire)); ! 1802: ! 1803: if (argc == 1) { ! 1804: convert_to_string_ex(expires); ! 1805: zend_alter_ini_entry("session.cache_expire", sizeof("session.cache_expire"), Z_STRVAL_PP(expires), Z_STRLEN_PP(expires), ZEND_INI_USER, ZEND_INI_STAGE_RUNTIME); ! 1806: } ! 1807: } ! 1808: /* }}} */ ! 1809: ! 1810: /* {{{ static void php_register_var(zval** entry TSRMLS_DC) */ ! 1811: static void php_register_var(zval** entry TSRMLS_DC) ! 1812: { ! 1813: zval **value; ! 1814: ! 1815: if (Z_TYPE_PP(entry) == IS_ARRAY) { ! 1816: if (Z_ARRVAL_PP(entry)->nApplyCount > 1) { ! 1817: return; ! 1818: } ! 1819: ! 1820: zend_hash_internal_pointer_reset(Z_ARRVAL_PP(entry)); ! 1821: Z_ARRVAL_PP(entry)->nApplyCount++; ! 1822: ! 1823: while (zend_hash_get_current_data(Z_ARRVAL_PP(entry), (void**)&value) == SUCCESS) { ! 1824: php_register_var(value TSRMLS_CC); ! 1825: zend_hash_move_forward(Z_ARRVAL_PP(entry)); ! 1826: } ! 1827: ! 1828: Z_ARRVAL_PP(entry)->nApplyCount--; ! 1829: } else { ! 1830: convert_to_string_ex(entry); ! 1831: ! 1832: if ((strcmp(Z_STRVAL_PP(entry), "HTTP_SESSION_VARS") != 0) && ! 1833: (strcmp(Z_STRVAL_PP(entry), "_SESSION") != 0) ! 1834: ) { ! 1835: PS_ADD_VARL(Z_STRVAL_PP(entry), Z_STRLEN_PP(entry)); ! 1836: } ! 1837: } ! 1838: } ! 1839: /* }}} */ ! 1840: ! 1841: /* {{{ proto string session_encode(void) ! 1842: Serializes the current setup and returns the serialized representation */ ! 1843: static PHP_FUNCTION(session_encode) ! 1844: { ! 1845: int len; ! 1846: char *enc; ! 1847: ! 1848: if (zend_parse_parameters_none() == FAILURE) { ! 1849: return; ! 1850: } ! 1851: ! 1852: enc = php_session_encode(&len TSRMLS_CC); ! 1853: if (enc == NULL) { ! 1854: RETURN_FALSE; ! 1855: } ! 1856: ! 1857: RETVAL_STRINGL(enc, len, 0); ! 1858: } ! 1859: /* }}} */ ! 1860: ! 1861: /* {{{ proto bool session_decode(string data) ! 1862: Deserializes data and reinitializes the variables */ ! 1863: static PHP_FUNCTION(session_decode) ! 1864: { ! 1865: char *str; ! 1866: int str_len; ! 1867: ! 1868: if (PS(session_status) == php_session_none) { ! 1869: RETURN_FALSE; ! 1870: } ! 1871: ! 1872: if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &str, &str_len) == FAILURE) { ! 1873: return; ! 1874: } ! 1875: ! 1876: php_session_decode(str, str_len TSRMLS_CC); ! 1877: ! 1878: RETURN_TRUE; ! 1879: } ! 1880: /* }}} */ ! 1881: ! 1882: /* {{{ proto bool session_start(void) ! 1883: Begin session - reinitializes freezed variables, registers browsers etc */ ! 1884: static PHP_FUNCTION(session_start) ! 1885: { ! 1886: /* skipping check for non-zero args for performance reasons here ?*/ ! 1887: php_session_start(TSRMLS_C); ! 1888: ! 1889: if (PS(session_status) != php_session_active) { ! 1890: RETURN_FALSE; ! 1891: } ! 1892: RETURN_TRUE; ! 1893: } ! 1894: /* }}} */ ! 1895: ! 1896: /* {{{ proto bool session_destroy(void) ! 1897: Destroy the current session and all data associated with it */ ! 1898: static PHP_FUNCTION(session_destroy) ! 1899: { ! 1900: if (zend_parse_parameters_none() == FAILURE) { ! 1901: return; ! 1902: } ! 1903: ! 1904: RETURN_BOOL(php_session_destroy(TSRMLS_C) == SUCCESS); ! 1905: } ! 1906: /* }}} */ ! 1907: ! 1908: /* {{{ proto void session_unset(void) ! 1909: Unset all registered variables */ ! 1910: static PHP_FUNCTION(session_unset) ! 1911: { ! 1912: if (PS(session_status) == php_session_none) { ! 1913: RETURN_FALSE; ! 1914: } ! 1915: ! 1916: IF_SESSION_VARS() { ! 1917: HashTable *ht_sess_var; ! 1918: ! 1919: SEPARATE_ZVAL_IF_NOT_REF(&PS(http_session_vars)); ! 1920: ht_sess_var = Z_ARRVAL_P(PS(http_session_vars)); ! 1921: ! 1922: if (PG(register_globals)) { ! 1923: uint str_len; ! 1924: char *str; ! 1925: ulong num_key; ! 1926: HashPosition pos; ! 1927: ! 1928: zend_hash_internal_pointer_reset_ex(ht_sess_var, &pos); ! 1929: ! 1930: while (zend_hash_get_current_key_ex(ht_sess_var, &str, &str_len, &num_key, 0, &pos) == HASH_KEY_IS_STRING) { ! 1931: zend_delete_global_variable(str, str_len - 1 TSRMLS_CC); ! 1932: zend_hash_move_forward_ex(ht_sess_var, &pos); ! 1933: } ! 1934: } ! 1935: ! 1936: /* Clean $_SESSION. */ ! 1937: zend_hash_clean(ht_sess_var); ! 1938: } ! 1939: } ! 1940: /* }}} */ ! 1941: ! 1942: /* {{{ proto void session_write_close(void) ! 1943: Write session data and end session */ ! 1944: static PHP_FUNCTION(session_write_close) ! 1945: { ! 1946: php_session_flush(TSRMLS_C); ! 1947: } ! 1948: /* }}} */ ! 1949: ! 1950: /* {{{ proto bool session_register(mixed var_names [, mixed ...]) ! 1951: Adds varname(s) to the list of variables which are freezed at the session end */ ! 1952: static PHP_FUNCTION(session_register) ! 1953: { ! 1954: zval ***args = NULL; ! 1955: int num_args, i; ! 1956: ! 1957: if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "+", &args, &num_args) == FAILURE) { ! 1958: return; ! 1959: } ! 1960: ! 1961: if (PS(session_status) == php_session_none || PS(session_status) == php_session_disabled) { ! 1962: php_session_start(TSRMLS_C); ! 1963: } ! 1964: ! 1965: if (PS(session_status) == php_session_disabled) { ! 1966: if (args) { ! 1967: efree(args); ! 1968: } ! 1969: RETURN_FALSE; ! 1970: } ! 1971: ! 1972: for (i = 0; i < num_args; i++) { ! 1973: if (Z_TYPE_PP(args[i]) == IS_ARRAY) { ! 1974: SEPARATE_ZVAL(args[i]); ! 1975: } ! 1976: php_register_var(args[i] TSRMLS_CC); ! 1977: } ! 1978: ! 1979: if (args) { ! 1980: efree(args); ! 1981: } ! 1982: ! 1983: RETURN_TRUE; ! 1984: } ! 1985: /* }}} */ ! 1986: ! 1987: /* {{{ proto bool session_unregister(string varname) ! 1988: Removes varname from the list of variables which are freezed at the session end */ ! 1989: static PHP_FUNCTION(session_unregister) ! 1990: { ! 1991: char *p_name; ! 1992: int p_name_len; ! 1993: ! 1994: if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &p_name, &p_name_len) == FAILURE) { ! 1995: return; ! 1996: } ! 1997: ! 1998: IF_SESSION_VARS() { ! 1999: SEPARATE_ZVAL_IF_NOT_REF(&PS(http_session_vars)); ! 2000: PS_DEL_VARL(p_name, p_name_len); ! 2001: } ! 2002: ! 2003: RETURN_TRUE; ! 2004: } ! 2005: /* }}} */ ! 2006: ! 2007: /* {{{ proto bool session_is_registered(string varname) ! 2008: Checks if a variable is registered in session */ ! 2009: static PHP_FUNCTION(session_is_registered) ! 2010: { ! 2011: zval *p_var; ! 2012: char *p_name; ! 2013: int p_name_len; ! 2014: ! 2015: if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &p_name, &p_name_len) == FAILURE) { ! 2016: return; ! 2017: } ! 2018: ! 2019: if (PS(session_status) == php_session_none) { ! 2020: RETURN_FALSE; ! 2021: } ! 2022: ! 2023: IF_SESSION_VARS() { ! 2024: if (zend_hash_find(Z_ARRVAL_P(PS(http_session_vars)), p_name, p_name_len+1, (void **)&p_var) == SUCCESS) { ! 2025: RETURN_TRUE; ! 2026: } ! 2027: } ! 2028: RETURN_FALSE; ! 2029: } ! 2030: /* }}} */ ! 2031: ! 2032: /* {{{ arginfo */ ! 2033: ZEND_BEGIN_ARG_INFO_EX(arginfo_session_name, 0, 0, 0) ! 2034: ZEND_ARG_INFO(0, name) ! 2035: ZEND_END_ARG_INFO() ! 2036: ! 2037: ZEND_BEGIN_ARG_INFO_EX(arginfo_session_module_name, 0, 0, 0) ! 2038: ZEND_ARG_INFO(0, module) ! 2039: ZEND_END_ARG_INFO() ! 2040: ! 2041: ZEND_BEGIN_ARG_INFO_EX(arginfo_session_save_path, 0, 0, 0) ! 2042: ZEND_ARG_INFO(0, path) ! 2043: ZEND_END_ARG_INFO() ! 2044: ! 2045: ZEND_BEGIN_ARG_INFO_EX(arginfo_session_id, 0, 0, 0) ! 2046: ZEND_ARG_INFO(0, id) ! 2047: ZEND_END_ARG_INFO() ! 2048: ! 2049: ZEND_BEGIN_ARG_INFO_EX(arginfo_session_regenerate_id, 0, 0, 0) ! 2050: ZEND_ARG_INFO(0, delete_old_session) ! 2051: ZEND_END_ARG_INFO() ! 2052: ! 2053: ZEND_BEGIN_ARG_INFO_EX(arginfo_session_decode, 0, 0, 1) ! 2054: ZEND_ARG_INFO(0, data) ! 2055: ZEND_END_ARG_INFO() ! 2056: ! 2057: ZEND_BEGIN_ARG_INFO_EX(arginfo_session_register, 0, 0, 1) ! 2058: ZEND_ARG_INFO(0, name) ! 2059: ZEND_ARG_INFO(0, ...) ! 2060: ZEND_END_ARG_INFO() ! 2061: ! 2062: ZEND_BEGIN_ARG_INFO_EX(arginfo_session_unregister, 0, 0, 1) ! 2063: ZEND_ARG_INFO(0, name) ! 2064: ZEND_END_ARG_INFO() ! 2065: ! 2066: ZEND_BEGIN_ARG_INFO_EX(arginfo_session_is_registered, 0, 0, 1) ! 2067: ZEND_ARG_INFO(0, name) ! 2068: ZEND_END_ARG_INFO() ! 2069: ! 2070: ZEND_BEGIN_ARG_INFO(arginfo_session_void, 0) ! 2071: ZEND_END_ARG_INFO() ! 2072: ! 2073: ZEND_BEGIN_ARG_INFO_EX(arginfo_session_set_save_handler, 0, 0, 6) ! 2074: ZEND_ARG_INFO(0, open) ! 2075: ZEND_ARG_INFO(0, close) ! 2076: ZEND_ARG_INFO(0, read) ! 2077: ZEND_ARG_INFO(0, write) ! 2078: ZEND_ARG_INFO(0, destroy) ! 2079: ZEND_ARG_INFO(0, gc) ! 2080: ZEND_END_ARG_INFO() ! 2081: ! 2082: ZEND_BEGIN_ARG_INFO_EX(arginfo_session_cache_limiter, 0, 0, 0) ! 2083: ZEND_ARG_INFO(0, cache_limiter) ! 2084: ZEND_END_ARG_INFO() ! 2085: ! 2086: ZEND_BEGIN_ARG_INFO_EX(arginfo_session_cache_expire, 0, 0, 0) ! 2087: ZEND_ARG_INFO(0, new_cache_expire) ! 2088: ZEND_END_ARG_INFO() ! 2089: ! 2090: ZEND_BEGIN_ARG_INFO_EX(arginfo_session_set_cookie_params, 0, 0, 1) ! 2091: ZEND_ARG_INFO(0, lifetime) ! 2092: ZEND_ARG_INFO(0, path) ! 2093: ZEND_ARG_INFO(0, domain) ! 2094: ZEND_ARG_INFO(0, secure) ! 2095: ZEND_ARG_INFO(0, httponly) ! 2096: ZEND_END_ARG_INFO() ! 2097: /* }}} */ ! 2098: ! 2099: /* {{{ session_functions[] ! 2100: */ ! 2101: static const zend_function_entry session_functions[] = { ! 2102: PHP_FE(session_name, arginfo_session_name) ! 2103: PHP_FE(session_module_name, arginfo_session_module_name) ! 2104: PHP_FE(session_save_path, arginfo_session_save_path) ! 2105: PHP_FE(session_id, arginfo_session_id) ! 2106: PHP_FE(session_regenerate_id, arginfo_session_regenerate_id) ! 2107: PHP_FE(session_decode, arginfo_session_decode) ! 2108: PHP_DEP_FE(session_register, arginfo_session_register) ! 2109: PHP_DEP_FE(session_unregister, arginfo_session_unregister) ! 2110: PHP_DEP_FE(session_is_registered, arginfo_session_is_registered) ! 2111: PHP_FE(session_encode, arginfo_session_void) ! 2112: PHP_FE(session_start, arginfo_session_void) ! 2113: PHP_FE(session_destroy, arginfo_session_void) ! 2114: PHP_FE(session_unset, arginfo_session_void) ! 2115: PHP_FE(session_set_save_handler, arginfo_session_set_save_handler) ! 2116: PHP_FE(session_cache_limiter, arginfo_session_cache_limiter) ! 2117: PHP_FE(session_cache_expire, arginfo_session_cache_expire) ! 2118: PHP_FE(session_set_cookie_params, arginfo_session_set_cookie_params) ! 2119: PHP_FE(session_get_cookie_params, arginfo_session_void) ! 2120: PHP_FE(session_write_close, arginfo_session_void) ! 2121: PHP_FALIAS(session_commit, session_write_close, arginfo_session_void) ! 2122: PHP_FE_END ! 2123: }; ! 2124: /* }}} */ ! 2125: ! 2126: /* ******************************** ! 2127: * Module Setup and Destruction * ! 2128: ******************************** */ ! 2129: ! 2130: static PHP_RINIT_FUNCTION(session) /* {{{ */ ! 2131: { ! 2132: php_rinit_session_globals(TSRMLS_C); ! 2133: ! 2134: if (PS(mod) == NULL) { ! 2135: char *value; ! 2136: ! 2137: value = zend_ini_string("session.save_handler", sizeof("session.save_handler"), 0); ! 2138: if (value) { ! 2139: PS(mod) = _php_find_ps_module(value TSRMLS_CC); ! 2140: } ! 2141: } ! 2142: ! 2143: if (PS(serializer) == NULL) { ! 2144: char *value; ! 2145: ! 2146: value = zend_ini_string("session.serialize_handler", sizeof("session.serialize_handler"), 0); ! 2147: if (value) { ! 2148: PS(serializer) = _php_find_ps_serializer(value TSRMLS_CC); ! 2149: } ! 2150: } ! 2151: ! 2152: if (PS(mod) == NULL || PS(serializer) == NULL) { ! 2153: /* current status is unusable */ ! 2154: PS(session_status) = php_session_disabled; ! 2155: return SUCCESS; ! 2156: } ! 2157: ! 2158: if (PS(auto_start)) { ! 2159: php_session_start(TSRMLS_C); ! 2160: } ! 2161: ! 2162: return SUCCESS; ! 2163: } ! 2164: /* }}} */ ! 2165: ! 2166: static PHP_RSHUTDOWN_FUNCTION(session) /* {{{ */ ! 2167: { ! 2168: int i; ! 2169: ! 2170: php_session_flush(TSRMLS_C); ! 2171: php_rshutdown_session_globals(TSRMLS_C); ! 2172: ! 2173: /* this should NOT be done in php_rshutdown_session_globals() */ ! 2174: for (i = 0; i < 6; i++) { ! 2175: if (PS(mod_user_names).names[i] != NULL) { ! 2176: zval_ptr_dtor(&PS(mod_user_names).names[i]); ! 2177: PS(mod_user_names).names[i] = NULL; ! 2178: } ! 2179: } ! 2180: ! 2181: return SUCCESS; ! 2182: } ! 2183: /* }}} */ ! 2184: ! 2185: static PHP_GINIT_FUNCTION(ps) /* {{{ */ ! 2186: { ! 2187: int i; ! 2188: ! 2189: ps_globals->save_path = NULL; ! 2190: ps_globals->session_name = NULL; ! 2191: ps_globals->id = NULL; ! 2192: ps_globals->mod = NULL; ! 2193: ps_globals->serializer = NULL; ! 2194: ps_globals->mod_data = NULL; ! 2195: ps_globals->session_status = php_session_none; ! 2196: for (i = 0; i < 6; i++) { ! 2197: ps_globals->mod_user_names.names[i] = NULL; ! 2198: } ! 2199: ps_globals->http_session_vars = NULL; ! 2200: } ! 2201: /* }}} */ ! 2202: ! 2203: static PHP_MINIT_FUNCTION(session) /* {{{ */ ! 2204: { ! 2205: zend_register_auto_global("_SESSION", sizeof("_SESSION")-1, NULL TSRMLS_CC); ! 2206: ! 2207: PS(module_number) = module_number; /* if we really need this var we need to init it in zts mode as well! */ ! 2208: ! 2209: PS(session_status) = php_session_none; ! 2210: REGISTER_INI_ENTRIES(); ! 2211: ! 2212: #ifdef HAVE_LIBMM ! 2213: PHP_MINIT(ps_mm) (INIT_FUNC_ARGS_PASSTHRU); ! 2214: #endif ! 2215: return SUCCESS; ! 2216: } ! 2217: /* }}} */ ! 2218: ! 2219: static PHP_MSHUTDOWN_FUNCTION(session) /* {{{ */ ! 2220: { ! 2221: UNREGISTER_INI_ENTRIES(); ! 2222: ! 2223: #ifdef HAVE_LIBMM ! 2224: PHP_MSHUTDOWN(ps_mm) (SHUTDOWN_FUNC_ARGS_PASSTHRU); ! 2225: #endif ! 2226: ! 2227: ps_serializers[PREDEFINED_SERIALIZERS].name = NULL; ! 2228: memset(&ps_modules[PREDEFINED_MODULES], 0, (MAX_MODULES-PREDEFINED_MODULES)*sizeof(ps_module *)); ! 2229: ! 2230: return SUCCESS; ! 2231: } ! 2232: /* }}} */ ! 2233: ! 2234: static PHP_MINFO_FUNCTION(session) /* {{{ */ ! 2235: { ! 2236: ps_module **mod; ! 2237: ps_serializer *ser; ! 2238: smart_str save_handlers = {0}; ! 2239: smart_str ser_handlers = {0}; ! 2240: int i; ! 2241: ! 2242: /* Get save handlers */ ! 2243: for (i = 0, mod = ps_modules; i < MAX_MODULES; i++, mod++) { ! 2244: if (*mod && (*mod)->s_name) { ! 2245: smart_str_appends(&save_handlers, (*mod)->s_name); ! 2246: smart_str_appendc(&save_handlers, ' '); ! 2247: } ! 2248: } ! 2249: ! 2250: /* Get serializer handlers */ ! 2251: for (i = 0, ser = ps_serializers; i < MAX_SERIALIZERS; i++, ser++) { ! 2252: if (ser && ser->name) { ! 2253: smart_str_appends(&ser_handlers, ser->name); ! 2254: smart_str_appendc(&ser_handlers, ' '); ! 2255: } ! 2256: } ! 2257: ! 2258: php_info_print_table_start(); ! 2259: php_info_print_table_row(2, "Session Support", "enabled" ); ! 2260: ! 2261: if (save_handlers.c) { ! 2262: smart_str_0(&save_handlers); ! 2263: php_info_print_table_row(2, "Registered save handlers", save_handlers.c); ! 2264: smart_str_free(&save_handlers); ! 2265: } else { ! 2266: php_info_print_table_row(2, "Registered save handlers", "none"); ! 2267: } ! 2268: ! 2269: if (ser_handlers.c) { ! 2270: smart_str_0(&ser_handlers); ! 2271: php_info_print_table_row(2, "Registered serializer handlers", ser_handlers.c); ! 2272: smart_str_free(&ser_handlers); ! 2273: } else { ! 2274: php_info_print_table_row(2, "Registered serializer handlers", "none"); ! 2275: } ! 2276: ! 2277: php_info_print_table_end(); ! 2278: ! 2279: DISPLAY_INI_ENTRIES(); ! 2280: } ! 2281: /* }}} */ ! 2282: ! 2283: static const zend_module_dep session_deps[] = { /* {{{ */ ! 2284: ZEND_MOD_OPTIONAL("hash") ! 2285: ZEND_MOD_REQUIRED("spl") ! 2286: ZEND_MOD_END ! 2287: }; ! 2288: /* }}} */ ! 2289: ! 2290: zend_module_entry session_module_entry = { ! 2291: STANDARD_MODULE_HEADER_EX, ! 2292: NULL, ! 2293: session_deps, ! 2294: "session", ! 2295: session_functions, ! 2296: PHP_MINIT(session), PHP_MSHUTDOWN(session), ! 2297: PHP_RINIT(session), PHP_RSHUTDOWN(session), ! 2298: PHP_MINFO(session), ! 2299: NO_VERSION_YET, ! 2300: PHP_MODULE_GLOBALS(ps), ! 2301: PHP_GINIT(ps), ! 2302: NULL, ! 2303: NULL, ! 2304: STANDARD_MODULE_PROPERTIES_EX ! 2305: }; ! 2306: ! 2307: #ifdef COMPILE_DL_SESSION ! 2308: ZEND_GET_MODULE(session) ! 2309: #endif ! 2310: ! 2311: /* ! 2312: * Local variables: ! 2313: * tab-width: 4 ! 2314: * c-basic-offset: 4 ! 2315: * End: ! 2316: * vim600: noet sw=4 ts=4 fdm=marker ! 2317: * vim<600: sw=4 ts=4 ! 2318: */