📄 session.c
字号:
} PS_ADD_VARL(name, namelen); efree(name); } PHP_VAR_UNSERIALIZE_DESTROY(var_hash); return SUCCESS;}#define PS_DELIMITER '|'#define PS_UNDEF_MARKER '!'PS_SERIALIZER_ENCODE_FUNC(php){ smart_str buf = {0}; php_serialize_data_t var_hash; PS_ENCODE_VARS; PHP_VAR_SERIALIZE_INIT(var_hash); PS_ENCODE_LOOP( smart_str_appendl(&buf, key, key_length); if (memchr(key, PS_DELIMITER, key_length)) { PHP_VAR_SERIALIZE_DESTROY(var_hash); smart_str_free(&buf); return FAILURE; } smart_str_appendc(&buf, PS_DELIMITER); php_var_serialize(&buf, struc, &var_hash TSRMLS_CC); } else { smart_str_appendc(&buf, PS_UNDEF_MARKER); smart_str_appendl(&buf, key, key_length); smart_str_appendc(&buf, PS_DELIMITER); ); if (newlen) *newlen = buf.len; *newstr = buf.c; PHP_VAR_SERIALIZE_DESTROY(var_hash); return SUCCESS;}PS_SERIALIZER_DECODE_FUNC(php) { const char *p, *q; char *name; const char *endptr = val + vallen; zval *current; int namelen; int has_value; php_unserialize_data_t var_hash; PHP_VAR_UNSERIALIZE_INIT(var_hash); p = val; while (p < endptr) { zval **tmp; q = p; while (*q != PS_DELIMITER) if (++q >= endptr) goto break_outer_loop; if (p[0] == PS_UNDEF_MARKER) { p++; has_value = 0; } else { has_value = 1; } namelen = q - p; name = estrndup(p, namelen); q++; if (zend_hash_find(&EG(symbol_table), name, namelen + 1, (void **) &tmp) == SUCCESS) { if ((Z_TYPE_PP(tmp) == IS_ARRAY && Z_ARRVAL_PP(tmp) == &EG(symbol_table)) || *tmp == PS(http_session_vars)) { goto skip; } } if (has_value) { ALLOC_INIT_ZVAL(current); if (php_var_unserialize(¤t, (const unsigned char **)&q, endptr, &var_hash TSRMLS_CC)) { php_set_session_var(name, namelen, current, &var_hash TSRMLS_CC); } zval_ptr_dtor(¤t); } PS_ADD_VARL(name, namelen);skip: efree(name); p = q; }break_outer_loop: PHP_VAR_UNSERIALIZE_DESTROY(var_hash); return SUCCESS;}static void php_session_track_init(TSRMLS_D){ zval *session_vars = NULL; /* Unconditionally destroy existing arrays -- possible dirty data */ zend_hash_del(&EG(symbol_table), "HTTP_SESSION_VARS", sizeof("HTTP_SESSION_VARS")); zend_hash_del(&EG(symbol_table), "_SESSION", sizeof("_SESSION")); if (PS(http_session_vars)) { zval_ptr_dtor(&PS(http_session_vars)); } MAKE_STD_ZVAL(session_vars); array_init(session_vars); PS(http_session_vars) = session_vars; ZEND_SET_GLOBAL_VAR_WITH_LENGTH("HTTP_SESSION_VARS", sizeof("HTTP_SESSION_VARS"), PS(http_session_vars), 3, 1); ZEND_SET_GLOBAL_VAR_WITH_LENGTH("_SESSION", sizeof("_SESSION"), PS(http_session_vars), 3, 1);}static char *php_session_encode(int *newlen TSRMLS_DC){ char *ret = NULL; IF_SESSION_VARS() { if (!PS(serializer)) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unknown session.serialize_handler. Failed to encode session object."); ret = NULL; } else if (PS(serializer)->encode(&ret, newlen TSRMLS_CC) == FAILURE) ret = NULL; } else { php_error_docref(NULL TSRMLS_CC, E_WARNING, "Cannot encode non-existent session."); } return ret;}static void php_session_decode(const char *val, int vallen TSRMLS_DC){ if (!PS(serializer)) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unknown session.serialize_handler. Failed to decode session object."); return; } if (PS(serializer)->decode(val, vallen TSRMLS_CC) == FAILURE) { php_session_destroy(TSRMLS_C); php_error_docref(NULL TSRMLS_CC, E_WARNING, "Failed to decode session object. Session has been destroyed."); }}static char hexconvtab[] = "0123456789abcdef";char *php_session_create_id(PS_CREATE_SID_ARGS){ PHP_MD5_CTX context; unsigned char digest[16]; char buf[256]; struct timeval tv; int i; int j = 0; unsigned char c; gettimeofday(&tv, NULL); PHP_MD5Init(&context); sprintf(buf, "%ld%ld%0.8f", tv.tv_sec, tv.tv_usec, php_combined_lcg(TSRMLS_C) * 10); PHP_MD5Update(&context, buf, strlen(buf)); if (PS(entropy_length) > 0) { int fd; fd = VCWD_OPEN(PS(entropy_file), O_RDONLY); if (fd >= 0) { unsigned char buf[2048]; int n; int to_read = PS(entropy_length); while (to_read > 0) { n = read(fd, buf, MIN(to_read, sizeof(buf))); if (n <= 0) break; PHP_MD5Update(&context, buf, n); to_read -= n; } close(fd); } } PHP_MD5Final(digest, &context); for (i = 0; i < 16; i++) { c = digest[i]; buf[j++] = hexconvtab[c >> 4]; buf[j++] = hexconvtab[c & 15]; } buf[j] = '\0'; if (newlen) *newlen = j; return estrdup(buf);}static void php_session_initialize(TSRMLS_D){ char *val; int vallen; /* check session name for invalid characters */ if (PS(id) && strpbrk(PS(id), "\r\n\t <>'\"\\")) { efree(PS(id)); PS(id) = NULL; } if (!PS(mod)) { php_error_docref(NULL TSRMLS_CC, E_ERROR, "No storage module chosen - failed to initialize session."); return; } /* Open session handler first */ if (PS(mod)->s_open(&PS(mod_data), PS(save_path), PS(session_name) TSRMLS_CC) == FAILURE) { php_error_docref(NULL TSRMLS_CC, E_ERROR, "Failed to initialize storage module: %s (path: %s)", PS(mod)->s_name, PS(save_path)); return; } /* If there is no ID, use session module to create one */ if (!PS(id)) PS(id) = PS(mod)->s_create_sid(&PS(mod_data), NULL TSRMLS_CC); /* Read data */ /* Question: if you create a SID here, should you also try to read data? * I'm not sure, but while not doing so will remove one session operation * it could prove usefull for those sites which wish to have "default" * session information */ php_session_track_init(TSRMLS_C); if (PS(mod)->s_read(&PS(mod_data), PS(id), &val, &vallen TSRMLS_CC) == SUCCESS) { php_session_decode(val, vallen TSRMLS_CC); efree(val); }}static int migrate_global(HashTable *ht, HashPosition *pos TSRMLS_DC){ char *str; uint str_len; ulong num_key; int n; zval **val; int ret = 0; n = zend_hash_get_current_key_ex(ht, &str, &str_len, &num_key, 0, pos); switch (n) { case HASH_KEY_IS_STRING: if (zend_hash_find(&EG(symbol_table), str, str_len, (void **) &val) == SUCCESS && val && Z_TYPE_PP(val) != IS_NULL) { ZEND_SET_SYMBOL_WITH_LENGTH(ht, str, str_len, *val, (*val)->refcount + 1 , 1); ret = 1; } break; case HASH_KEY_IS_LONG: php_error_docref(NULL TSRMLS_CC, E_NOTICE, "The session bug compatibility code will not " "try to locate the global variable $%lu due to its " "numeric nature.", num_key); break; } return ret;}static void php_session_save_current_state(TSRMLS_D){ int ret = FAILURE; IF_SESSION_VARS() { if (PS(bug_compat) && !PG(register_globals)) { HashTable *ht = Z_ARRVAL_P(PS(http_session_vars)); HashPosition pos; zval **val; int do_warn = 0; zend_hash_internal_pointer_reset_ex(ht, &pos); while (zend_hash_get_current_data_ex(ht, (void **) &val, &pos) != FAILURE) { if (Z_TYPE_PP(val) == IS_NULL) { if (migrate_global(ht, &pos TSRMLS_CC)) do_warn = 1; } zend_hash_move_forward_ex(ht, &pos); } if (do_warn && PS(bug_compat_warn)) { 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."); } } if (PS(mod_data)) { char *val; int vallen; val = php_session_encode(&vallen TSRMLS_CC); if (val) { ret = PS(mod)->s_write(&PS(mod_data), PS(id), val, vallen TSRMLS_CC); efree(val); } else { ret = PS(mod)->s_write(&PS(mod_data), PS(id), "", 0 TSRMLS_CC); } } if (ret == FAILURE) php_error_docref(NULL TSRMLS_CC, E_WARNING, "Failed to write session data (%s). Please " "verify that the current setting of session.save_path " "is correct (%s)", PS(mod)->s_name, PS(save_path)); } if (PS(mod_data)) PS(mod)->s_close(&PS(mod_data) TSRMLS_CC);}static char *month_names[] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"};static char *week_days[] = { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"};static void strcpy_gmt(char *ubuf, time_t *when){ char buf[MAX_STR]; struct tm tm; int n; php_gmtime_r(when, &tm); n = sprintf(buf, "%s, %02d %s %d %02d:%02d:%02d GMT", /* SAFE */ week_days[tm.tm_wday], tm.tm_mday, month_names[tm.tm_mon], tm.tm_year + 1900, tm.tm_hour, tm.tm_min, tm.tm_sec); memcpy(ubuf, buf, n); ubuf[n] = '\0';}static void last_modified(TSRMLS_D){ const char *path; struct stat sb; char buf[MAX_STR + 1]; path = SG(request_info).path_translated; if (path) { if (VCWD_STAT(path, &sb) == -1) { return; }#define LAST_MODIFIED "Last-Modified: " memcpy(buf, LAST_MODIFIED, sizeof(LAST_MODIFIED) - 1); strcpy_gmt(buf + sizeof(LAST_MODIFIED) - 1, &sb.st_mtime); ADD_HEADER(buf); }}CACHE_LIMITER_FUNC(public){ char buf[MAX_STR + 1]; struct timeval tv; time_t now; gettimeofday(&tv, NULL); now = tv.tv_sec + PS(cache_expire) * 60;#define EXPIRES "Expires: " memcpy(buf, EXPIRES, sizeof(EXPIRES) - 1); strcpy_gmt(buf + sizeof(EXPIRES) - 1, &now); ADD_HEADER(buf); sprintf(buf, "Cache-Control: public, max-age=%ld", PS(cache_expire) * 60); /* SAFE */ ADD_HEADER(buf); last_modified(TSRMLS_C);}CACHE_LIMITER_FUNC(private_no_expire){ char buf[MAX_STR + 1]; sprintf(buf, "Cache-Control: private, max-age=%ld, pre-check=%ld", PS(cache_expire) * 60, PS(cache_expire) * 60); /* SAFE */ ADD_HEADER(buf); last_modified(TSRMLS_C);}CACHE_LIMITER_FUNC(private){ ADD_HEADER("Expires: Thu, 19 Nov 1981 08:52:00 GMT"); CACHE_LIMITER(private_no_expire)(TSRMLS_C);}CACHE_LIMITER_FUNC(nocache){ ADD_HEADER("Expires: Thu, 19 Nov 1981 08:52:00 GMT"); /* For HTTP/1.1 conforming clients and the rest (MSIE 5) */ ADD_HEADER("Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0"); /* For HTTP/1.0 conforming clients */ ADD_HEADER("Pragma: no-cache");}static php_session_cache_limiter_t php_session_cache_limiters[] = { CACHE_LIMITER_ENTRY(public) CACHE_LIMITER_ENTRY(private) CACHE_LIMITER_ENTRY(private_no_expire) CACHE_LIMITER_ENTRY(nocache) {0}};static int php_session_cache_limiter(TSRMLS_D){ php_session_cache_limiter_t *lim; if (PS(cache_limiter)[0] == '\0') return 0; if (SG(headers_sent)) { char *output_start_filename = php_get_output_start_filename(TSRMLS_C); int output_start_lineno = php_get_output_start_lineno(TSRMLS_C); if (output_start_filename) { 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); } else { php_error_docref(NULL TSRMLS_CC, E_WARNING, "Cannot send session cache limiter - headers already sent"); } return -2; } for (lim = php_session_cache_limiters; lim->name; lim++) { if (!strcasecmp(lim->name, PS(cache_limiter))) { lim->func(TSRMLS_C); return 0; } } return -1;}#define COOKIE_SET_COOKIE "Set-Cookie: "#define COOKIE_EXPIRES "; expires="#define COOKIE_PATH "; path="#define COOKIE_DOMAIN "; domain="#define COOKIE_SECURE "; secure"static void php_session_send_cookie(TSRMLS_D){ smart_str ncookie = {0}; char *date_fmt = NULL;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -