PHP  
 PHP: Test and Code Coverage Analysis
downloads | QA | documentation | faq | getting help | mailing lists | reporting bugs | php.net sites | links | my php.net 
 

LTP GCOV extension - code coverage report
Current view: directory - session - session.c
Test: PHP Code Coverage
Date: 2009-11-23 Instrumented lines: 955
Code covered: 76.1 % Executed lines: 727
Legend: not executed executed

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

Generated by: LTP GCOV extension version 1.5

Generated at Mon, 23 Nov 2009 17:39:37 +0000 (36 hours ago)

Copyright © 2005-2009 The PHP Group
All rights reserved.