[EMAIL PROTECTED] wrote:
> I had a report of a problem with mod_mm and msession. If you configure PHP 
> to use both msession and the mm session handler, you will render apache 
> unable to start.


I'm using patched session module and I don't have problem with running
msession, mm, pgsql (haven't tried srm, yet)

> 
> The session.save_path is used by both msession and mod_mm. When mod_mm 
> uses it, it expects it to be a valid working directory. When msesion uses 
> it, it expects it to be a server host name which is running the msessiond 
> daemon. 

> If mod_mm does not find a valid working directory, it will fail at module 
> init, thus preventing apache from starting.

> The short term solution is chose msession or mod_mm, but not both. The 
> long term solution is to create an "[msession]" category in the php.ini 
> file, and use msession.server_host as a key.
> 
> I can not get to it this week, but anyone with some spare time is welcome 
> to have at it.
> 


Patch takes care of these, too.
I attached latest diff.
The only problem I have now is I cannot load session_pgsql, msession
modul from php.ini or dl().

Could you tell me if this patch works well for you?


PS: It also includes output buffer patch, but it does not do
anything bad AFAIK.

-- 
Yasuo Ohgaki
Index: ext/session/mod_files.c
===================================================================
RCS file: /repository/php4/ext/session/mod_files.c,v
retrieving revision 1.67
diff -u -r1.67 mod_files.c
--- ext/session/mod_files.c     3 Feb 2002 05:40:19 -0000       1.67
+++ ext/session/mod_files.c     16 Feb 2002 05:34:01 -0000
@@ -16,7 +16,7 @@
    +----------------------------------------------------------------------+
  */
 
-/* $Id: mod_files.c,v 1.67 2002/02/03 05:40:19 yohgaki Exp $ */
+/* $Id: mod_files.c,v 1.66 2002/02/03 03:17:35 yohgaki Exp $ */
 
 #include "php.h"
 
@@ -123,10 +123,9 @@
        }
 }
 
-static void ps_files_open(ps_files *data, const char *key)
+static int ps_files_open(ps_files *data, const char *key TSRMLS_DC)
 {
        char buf[MAXPATHLEN];
-       TSRMLS_FETCH();
 
        if (data->fd < 0 || !data->lastkey || strcmp(key, data->lastkey)) {
                if (data->lastkey) {
@@ -138,7 +137,7 @@
                
                if (!ps_files_valid_key(key) || 
                                !ps_files_path_create(buf, sizeof(buf), data, key))
-                       return;
+                       return FAILURE;
                
                data->lastkey = estrdup(key);
                
@@ -153,13 +152,16 @@
                if (data->fd != -1) 
                        flock(data->fd, LOCK_EX);
 
-               if (data->fd == -1)
+               if (data->fd == -1) {
                        php_error(E_WARNING, "open(%s, O_RDWR) failed: %s (%d)", buf, 
                                        strerror(errno), errno);
+                       return FAILURE;
+               }
        }
+       return SUCCESS;
 }
 
-static int ps_files_cleanup_dir(const char *dirname, int maxlifetime)
+static int ps_files_cleanup_dir(const char *dirname, int maxlifetime TSRMLS_DC)
 {
        DIR *dir;
        char dentry[sizeof(struct dirent) + MAXPATHLEN];
@@ -169,7 +171,6 @@
        time_t now;
        int nrdels = 0;
        size_t dirname_len;
-       TSRMLS_FETCH();
 
        dir = opendir(dirname);
        if (!dir) {
@@ -229,7 +230,7 @@
        }
        data->basedir_len = strlen(save_path);
        data->basedir = estrndup(save_path, data->basedir_len);
-       
+
        return SUCCESS;
 }
 
@@ -254,10 +255,8 @@
        struct stat sbuf;
        PS_FILES_DATA;
 
-       ps_files_open(data, key);
-       if (data->fd < 0)
+       if (ps_files_open(data, key TSRMLS_CC) == FAILURE)
                return FAILURE;
-       
        if (fstat(data->fd, &sbuf))
                return FAILURE;
        
@@ -283,8 +282,7 @@
        long n;
        PS_FILES_DATA;
 
-       ps_files_open(data, key);
-       if (data->fd < 0)
+       if (ps_files_open(data, key TSRMLS_CC) == FAILURE)
                return FAILURE;
 
        /* 
@@ -314,7 +312,6 @@
 {
        char buf[MAXPATHLEN];
        PS_FILES_DATA;
-       TSRMLS_FETCH();
 
        if (!ps_files_path_create(buf, sizeof(buf), data, key))
                return FAILURE;
@@ -337,7 +334,7 @@
           an external entity (i.e. find -ctime x | xargs rm) */
           
        if (data->dirdepth == 0)
-               *nrdels = ps_files_cleanup_dir(data->basedir, maxlifetime);
+               *nrdels = ps_files_cleanup_dir(data->basedir, maxlifetime TSRMLS_CC);
        
        return SUCCESS;
 }
Index: ext/session/mod_mm.c
===================================================================
RCS file: /repository/php4/ext/session/mod_mm.c,v
retrieving revision 1.31
diff -u -r1.31 mod_mm.c
--- ext/session/mod_mm.c        25 Jan 2002 20:59:24 -0000      1.31
+++ ext/session/mod_mm.c        16 Feb 2002 05:34:01 -0000
@@ -319,7 +319,6 @@
 {
        PS_MM_DATA;
        ps_sd *sd;
-       int ret = FAILURE;
 
        mm_lock(data->mm, MM_LOCK_RD);
        
@@ -329,12 +328,14 @@
                *val = emalloc(sd->datalen + 1);
                memcpy(*val, sd->data, sd->datalen);
                (*val)[sd->datalen] = '\0';
-               ret = SUCCESS;
        }
-
+       else {
+               *val = estrdup("");
+       }
+       
        mm_unlock(data->mm);
        
-       return ret;
+       return SUCCESS;
 }
 
 PS_WRITE_FUNC(mm)
Index: ext/session/mod_user.c
===================================================================
RCS file: /repository/php4/ext/session/mod_user.c,v
retrieving revision 1.20
diff -u -r1.20 mod_user.c
--- ext/session/mod_user.c      11 Dec 2001 15:30:21 -0000      1.20
+++ ext/session/mod_user.c      16 Feb 2002 05:34:01 -0000
@@ -51,11 +51,10 @@
 }
 
 
-static zval *ps_call_handler(zval *func, int argc, zval **argv)
+static zval *ps_call_handler(zval *func, int argc, zval **argv TSRMLS_DC)
 {
        int i;
        zval *retval = NULL;
-       TSRMLS_FETCH();
        
        MAKE_STD_ZVAL(retval);
        if (call_user_function(EG(function_table), NULL, func, retval, 
@@ -96,7 +95,7 @@
        SESS_ZVAL_STRING(save_path, args[0]);
        SESS_ZVAL_STRING(session_name, args[1]);
        
-       retval = ps_call_handler(PSF(open), 2, args);
+       retval = ps_call_handler(PSF(open), 2, args TSRMLS_CC);
        
        FINISH;
 }
@@ -106,7 +105,7 @@
        int i;
        STDVARS;
 
-       retval = ps_call_handler(PSF(close), 0, NULL);
+       retval = ps_call_handler(PSF(close), 0, NULL TSRMLS_CC);
 
        for (i = 0; i < 6; i++)
                zval_ptr_dtor(&mdata->names[i]);
@@ -124,7 +123,7 @@
 
        SESS_ZVAL_STRING(key, args[0]);
 
-       retval = ps_call_handler(PSF(read), 1, args);
+       retval = ps_call_handler(PSF(read), 1, args TSRMLS_CC);
        
        if (retval) {
                if (Z_TYPE_P(retval) == IS_STRING) {
@@ -146,7 +145,7 @@
        SESS_ZVAL_STRING(key, args[0]);
        SESS_ZVAL_STRINGN(val, vallen, args[1]);
 
-       retval = ps_call_handler(PSF(write), 2, args);
+       retval = ps_call_handler(PSF(write), 2, args TSRMLS_CC);
 
        FINISH;
 }
@@ -158,7 +157,7 @@
 
        SESS_ZVAL_STRING(key, args[0]);
 
-       retval = ps_call_handler(PSF(destroy), 1, args);
+       retval = ps_call_handler(PSF(destroy), 1, args TSRMLS_CC);
 
        FINISH;
 }
@@ -170,7 +169,7 @@
 
        SESS_ZVAL_LONG(maxlifetime, args[0]);
 
-       retval = ps_call_handler(PSF(gc), 1, args);
+       retval = ps_call_handler(PSF(gc), 1, args TSRMLS_CC);
 
        FINISH;
 }
Index: ext/session/php_session.h
===================================================================
RCS file: /repository/php4/ext/session/php_session.h,v
retrieving revision 1.69
diff -u -r1.69 php_session.h
--- ext/session/php_session.h   7 Feb 2002 22:00:21 -0000       1.69
+++ ext/session/php_session.h   16 Feb 2002 05:34:01 -0000
@@ -21,12 +21,12 @@
 
 #include "ext/standard/php_var.h"
 
-#define PS_OPEN_ARGS void **mod_data, const char *save_path, const char *session_name
-#define PS_CLOSE_ARGS void **mod_data
-#define PS_READ_ARGS void **mod_data, const char *key, char **val, int *vallen
-#define PS_WRITE_ARGS void **mod_data, const char *key, const char *val, const int 
vallen
-#define PS_DESTROY_ARGS void **mod_data, const char *key
-#define PS_GC_ARGS void **mod_data, int maxlifetime, int *nrdels
+#define PS_OPEN_ARGS void **mod_data, const char *save_path, const char *session_name 
+TSRMLS_DC
+#define PS_CLOSE_ARGS void **mod_data TSRMLS_DC
+#define PS_READ_ARGS void **mod_data, const char *key, char **val, int *vallen 
+TSRMLS_DC
+#define PS_WRITE_ARGS void **mod_data, const char *key, const char *val, const int 
+vallen TSRMLS_DC
+#define PS_DESTROY_ARGS void **mod_data, const char *key TSRMLS_DC
+#define PS_GC_ARGS void **mod_data, int maxlifetime, int *nrdels TSRMLS_DC
 
 typedef struct ps_module_struct {
        const char *name;
@@ -61,11 +61,16 @@
        #x, ps_open_##x, ps_close_##x, ps_read_##x, ps_write_##x, \
         ps_delete_##x, ps_gc_##x 
 
-typedef enum {
-       php_session_disabled,
-       php_session_none,
-       php_session_active
-} php_session_status;
+/* typedef enum { */
+/*     php_session_disabled, */
+/*     php_session_none, */
+/*     php_session_active */
+/* } php_session_status; */
+
+#define PS_DISABLED     1
+#define PS_NONE         2
+#define PS_ACTIVE       4
+#define PS_ERROR        8
 
 typedef struct _php_ps_globals {
        char *save_path;
@@ -79,10 +84,11 @@
        char *cookie_path;
        char *cookie_domain;
        zend_bool  cookie_secure;
+       long rinit_mod;
        ps_module *mod;
        void *mod_data;
        HashTable vars;
-       php_session_status session_status;
+       long session_status;
        long gc_probability;
        long gc_maxlifetime;
        int module_number;
Index: ext/session/session.c
===================================================================
RCS file: /repository/php4/ext/session/session.c,v
retrieving revision 1.276
diff -u -r1.276 session.c
--- ext/session/session.c       7 Feb 2002 22:00:21 -0000       1.276
+++ ext/session/session.c       16 Feb 2002 05:34:02 -0000
@@ -83,7 +83,7 @@
 
 static void php_session_output_handler(char *output, uint output_len, char 
**handled_output, uint *handled_output_len, int mode TSRMLS_DC)
 {
-       if ((PS(session_status) == php_session_active)) {
+       if ((PS(session_status) & PS_ACTIVE)) {
                *handled_output = url_adapt_ext_ex(output, output_len, 
PS(session_name), PS(id), handled_output_len, (zend_bool) (mode&PHP_OUTPUT_HANDLER_END 
? 1 : 0) TSRMLS_CC);
        } else {
                *handled_output = NULL;
@@ -95,8 +95,8 @@
 {
        php_url_scanner_activate(TSRMLS_C);
        php_url_scanner_ex_activate(TSRMLS_C);
-       php_start_ob_buffer(NULL, chunk_size TSRMLS_CC);
-       php_ob_set_internal_handler(php_session_output_handler, chunk_size TSRMLS_CC);
+       php_start_ob_buffer(NULL, chunk_size, 1 TSRMLS_CC);
+       php_ob_set_internal_handler(php_session_output_handler, chunk_size, "trans sid 
+session", 1 TSRMLS_CC);
        PS(output_handler_registered) = 1;
 }
 
@@ -124,9 +124,12 @@
 static PHP_INI_MH(OnUpdateSerializer)
 {
        PS(serializer) = _php_find_ps_serializer(new_value TSRMLS_CC);
-       if(!PS(serializer)) {
-         php_error(E_ERROR,"Cannot find serialization handler %s",new_value);
-       }         
+/* Following lines are commented out to prevent bogus error message at
+   start up. i.e. Serializer modules are not initilzied before Session
+   module. */
+/*     if(!PS(serializer)) { */
+/*       php_error(E_ERROR,"Cannot find serialization handler %s",new_value); */
+/*     }          */
        return SUCCESS;
 }
 
@@ -297,10 +300,7 @@
                if (zend_hash_find(Z_ARRVAL_P(PS(http_session_vars)), name, namelen+1, 
(void **) state_var)==SUCCESS) {
                        return SUCCESS;
                }
-       } else if (!PG(register_globals)) {
-               /* register_globals is disabled, but we don't have http_session_vars */
-               return HASH_KEY_NON_EXISTANT;
-       }       
+       }
        return zend_hash_find(&EG(symbol_table), name, namelen+1, (void **) state_var);
 }
 
@@ -473,19 +473,27 @@
 {
        char *ret = NULL;
 
-       if (PS(serializer)->encode(&ret, newlen TSRMLS_CC) == FAILURE)
+       if (PS(serializer)->encode(&ret, newlen TSRMLS_CC) == FAILURE) {
+               PS(session_status) = PS_ERROR;
                ret = NULL;
-
+       }
+       
        return ret;
 }
 
-static void php_session_decode(const char *val, int vallen TSRMLS_DC)
+static int php_session_decode(const char *val, int vallen TSRMLS_DC)
 {
-       php_session_track_init(TSRMLS_C);
-       if (PS(serializer)->decode(val, vallen TSRMLS_CC) == FAILURE) {
-               php_session_destroy(TSRMLS_C);
-               php_error(E_WARNING, "Failed to decode session object. Session has 
been destroyed.");
+       if (PS(session_status) & PS_ACTIVE) {
+               php_session_track_init(TSRMLS_C);
+               if (PS(serializer)->decode(val, vallen TSRMLS_CC) == FAILURE) {
+                       PS(session_status) = PS_ERROR;
+                       php_session_destroy(TSRMLS_C);
+                       php_error(E_WARNING, "Failed to decode session object. Session 
+has been destroyed.");
+                       return FAILURE;
+               }
+               return SUCCESS;
        }
+       return FAILURE;
 }
 
 static char hexconvtab[] = "0123456789abcdef";
@@ -544,14 +552,18 @@
        char *val;
        int vallen;
        
-       if (PS(mod)->open(&PS(mod_data), PS(save_path), PS(session_name)) == FAILURE) {
-               php_error(E_ERROR, "Failed to initialize session module");
+       if (PS(mod)->open(&PS(mod_data), PS(save_path), PS(session_name) TSRMLS_CC) == 
+FAILURE) {
+               PS(session_status) = PS_ERROR;
+               php_error(E_WARNING, "Failed to initialize session module");
                return;
        }
-       if (PS(mod)->read(&PS(mod_data), PS(id), &val, &vallen) == SUCCESS) {
-               php_session_decode(val, vallen TSRMLS_CC);
-               efree(val);
+       if (PS(mod)->read(&PS(mod_data), PS(id), &val, &vallen TSRMLS_CC) == FAILURE) {
+               PS(session_status) = PS_ERROR;
+               php_error(E_WARNING, "Failed to read session data");
+               return;
        }
+       php_session_decode(val, vallen TSRMLS_CC);
+       efree(val);
 }
 
 
@@ -565,38 +577,37 @@
        ulong num_key;
        HashPosition pos;
        
-       if (!PG(register_globals) && !PS(http_session_vars)) {
+       if (PS(session_status) & (PS_DISABLED|PS_NONE|PS_ERROR)) {
                return;
        }
                
-       if (PS(http_session_vars)) {
-               for 
(zend_hash_internal_pointer_reset_ex(Z_ARRVAL_P(PS(http_session_vars)), &pos);
-                               
zend_hash_get_current_key_ex(Z_ARRVAL_P(PS(http_session_vars)), &variable, 
&variable_len, &num_key, 0, &pos) == HASH_KEY_IS_STRING;
-                               
zend_hash_move_forward_ex(Z_ARRVAL_P(PS(http_session_vars)),&pos)) {
-                       PS_ADD_VARL(variable,variable_len-1);
-               }
+       for (zend_hash_internal_pointer_reset_ex(Z_ARRVAL_P(PS(http_session_vars)), 
+&pos);
+                zend_hash_get_current_key_ex(Z_ARRVAL_P(PS(http_session_vars)), 
+&variable, &variable_len, &num_key, 0, &pos) == HASH_KEY_IS_STRING;
+                zend_hash_move_forward_ex(Z_ARRVAL_P(PS(http_session_vars)),&pos)) {
+               PS_ADD_VARL(variable,variable_len-1);
        }
 
        if (PS(mod_data)) {
                val = php_session_encode(&vallen TSRMLS_CC);
                if (val) {
-                       ret = PS(mod)->write(&PS(mod_data), PS(id), val, vallen);
+                       ret = PS(mod)->write(&PS(mod_data), PS(id), val, vallen 
+TSRMLS_CC);
                        efree(val);
                } else {
-                       ret = PS(mod)->write(&PS(mod_data), PS(id), "", 0);
+                       ret = PS(mod)->write(&PS(mod_data), PS(id), "", 0 TSRMLS_CC);
                }
        }
        
-       if (ret == FAILURE)
+       if (ret == FAILURE) {
+               PS(session_status) = PS_ERROR;
                php_error(E_WARNING, "Failed to write session data (%s). Please "
-                               "verify that the current setting of session.save_path "
-                               "is correct (%s)",
-                               PS(mod)->name,
-                               PS(save_path));
-       
+                                 "verify that the current setting of 
+session.save_path "
+                                 "is correct (%s)",
+                                 PS(mod)->name,
+                                 PS(save_path));
+       }
        
        if (PS(mod_data))
-               PS(mod)->close(&PS(mod_data));
+               PS(mod)->close(&PS(mod_data) TSRMLS_CC);
 }
 
 static char *month_names[] = {
@@ -740,6 +751,7 @@
        smart_str ncookie = {0};
        char *date_fmt = NULL;
 
+
        if (SG(headers_sent)) {
                char *output_start_filename = php_get_output_start_filename(TSRMLS_C);
                int output_start_lineno = php_get_output_start_lineno(TSRMLS_C);
@@ -830,10 +842,11 @@
        int module_number = PS(module_number);
        int nrand;
        int lensess;
+       smart_str var = {0};
 
        PS(apply_trans_sid) = PS(use_trans_sid);
 
-       if (PS(session_status) != php_session_none) 
+       if (PS(session_status) & (PS_ACTIVE|PS_ERROR)) 
                return;
 
        lensess = strlen(PS(session_name));
@@ -923,33 +936,26 @@
                php_session_send_cookie(TSRMLS_C);
        }
 
-
-       if (PS(apply_trans_sid)) {
-               smart_str var = {0};
-
-               smart_str_appends(&var, PS(session_name));
-               smart_str_appendc(&var, '=');
-               smart_str_appends(&var, PS(id));
-               smart_str_0(&var);
-               REGISTER_STRING_CONSTANT("SID", var.c, 0);
-       } else {
-               REGISTER_STRING_CONSTANT("SID", empty_string, 0);
-       }
-
-       PS(session_status) = php_session_active;
+       smart_str_appends(&var, PS(session_name));
+       smart_str_appendc(&var, '=');
+       smart_str_appends(&var, PS(id));
+       smart_str_0(&var);
+       REGISTER_STRING_CONSTANT("SID", var.c, 0);
        if (PS(apply_trans_sid)) {
                php_session_start_output_handler(4096 TSRMLS_CC);
        }
 
+       PS(session_status) = PS_ACTIVE;
+
        php_session_cache_limiter(TSRMLS_C);
        php_session_initialize(TSRMLS_C);
 
-       if (PS(mod_data) && PS(gc_probability) > 0) {
+       if ((PS(session_status) & PS_ACTIVE) && PS(gc_probability) > 0) {
                int nrdels = -1;
-
+               
                nrand = (int) (100.0*php_combined_lcg(TSRMLS_C));
                if (nrand < PS(gc_probability)) {
-                       PS(mod)->gc(&PS(mod_data), PS(gc_maxlifetime), &nrdels);
+                       PS(mod)->gc(&PS(mod_data), PS(gc_maxlifetime), &nrdels 
+TSRMLS_CC);
 #if 0
                        if (nrdels != -1)
                                php_error(E_NOTICE, "purged %d expired session 
objects\n", nrdels);
@@ -958,18 +964,20 @@
        }
 }
 
+
 static zend_bool php_session_destroy(TSRMLS_D)
 {
        zend_bool retval = SUCCESS;
 
-       if (PS(session_status) != php_session_active) {
-               php_error(E_WARNING, "Trying to destroy uninitialized session");
+       if (PS(session_status) & (PS_DISABLED|PS_NONE|PS_ERROR)) {
+               php_error(E_NOTICE, "Trying to destroy uninitialized session");
                return FAILURE;
        }
 
-       if (PS(mod)->destroy(&PS(mod_data), PS(id)) == FAILURE) {
+       if (PS(mod)->destroy(&PS(mod_data), PS(id) TSRMLS_CC) == FAILURE) {
+               PS(session_status) = PS_ERROR;          
                retval = FAILURE;
-               php_error(E_WARNING, "Session object destruction failed");
+               php_error(E_NOTICE, "Session object destruction failed");
        }
        
        php_rshutdown_session_globals(TSRMLS_C);
@@ -985,20 +993,24 @@
 {
     zval **lifetime, **path, **domain, **secure;
 
-       if (!PS(use_cookies))
-               return;
 
     if (ZEND_NUM_ARGS() < 1 || ZEND_NUM_ARGS() > 4 ||
                zend_get_parameters_ex(ZEND_NUM_ARGS(), &lifetime, &path, &domain, 
&secure) == FAILURE)
                WRONG_PARAM_COUNT;
 
+       if (!PS(use_cookies)) {
+               php_error(E_NOTICE, "%s() cannot set cookie parameter when use_cookies 
+is off",
+                                 get_active_function_name(TSRMLS_C));
+               RETURN_FALSE;
+       }
+
        convert_to_long_ex(lifetime);
        PS(cookie_lifetime) = Z_LVAL_PP(lifetime);
 
        if (ZEND_NUM_ARGS() > 1) {
                convert_to_string_ex(path);
                zend_alter_ini_entry("session.cookie_path", 
sizeof("session.cookie_path"), Z_STRVAL_PP(path), Z_STRLEN_PP(path), PHP_INI_USER, 
PHP_INI_STAGE_RUNTIME);
-
+               
                if (ZEND_NUM_ARGS() > 2) {
                        convert_to_string_ex(domain);
                        zend_alter_ini_entry("session.cookie_domain", 
sizeof("session.cookie_domain"), Z_STRVAL_PP(domain), Z_STRLEN_PP(domain), 
PHP_INI_USER, PHP_INI_STAGE_RUNTIME);
@@ -1008,6 +1020,7 @@
                        }
                }
        }
+       
 }
 /* }}} */
 
@@ -1020,7 +1033,8 @@
        }
 
        if (array_init(return_value) == FAILURE) {
-               php_error(E_ERROR, "Cannot initialize return value from 
session_get_cookie_parameters");
+               php_error(E_ERROR, "%s() cannot initialize return value from 
+session_get_cookie_parameters",
+                                 get_active_function_name(TSRMLS_C));
                RETURN_FALSE;
        }
 
@@ -1037,18 +1051,22 @@
 {
        zval **p_name;
        int ac = ZEND_NUM_ARGS();
-       char *old;
-
-       old = estrdup(PS(session_name));
+       char *old = NULL;
 
        if (ac < 0 || ac > 1 || zend_get_parameters_ex(ac, &p_name) == FAILURE)
                WRONG_PARAM_COUNT;
 
        if (ac == 1) {
+               if (PS(session_status) & PS_ACTIVE) {
+                       php_error(E_NOTICE, "%s() cannot set session name once session 
+is started.",
+                                         get_active_function_name(TSRMLS_C));
+                       RETURN_FALSE;
+               }
                convert_to_string_ex(p_name);
                zend_alter_ini_entry("session.name", sizeof("session.name"), 
Z_STRVAL_PP(p_name), Z_STRLEN_PP(p_name), PHP_INI_USER, PHP_INI_STAGE_RUNTIME);
        }
-       
+
+       old = estrdup(PS(session_name));
        RETVAL_STRING(old, 0);
 }
 /* }}} */
@@ -1059,9 +1077,7 @@
 {
        zval **p_name;
        int ac = ZEND_NUM_ARGS();
-       char *old;
-
-       old = safe_estrdup(PS(mod)->name);
+       char *old = NULL;
 
        if (ac < 0 || ac > 1 || zend_get_parameters_ex(ac, &p_name) == FAILURE)
                WRONG_PARAM_COUNT;
@@ -1069,26 +1085,34 @@
        if (ac == 1) {
                ps_module *tempmod;
 
+               if (PS(session_status) & (PS_ACTIVE|PS_ERROR)) {
+                       php_error(E_NOTICE, "%s() cannot set session module name once 
+session is started. "
+                                         "Current session save handler (%s)",
+                                         get_active_function_name(TSRMLS_C),
+                                         (PS(mod)->name ? PS(mod)->name : "none"));
+                       RETURN_FALSE;
+               }
+                       
                convert_to_string_ex(p_name);
                tempmod = _php_find_ps_module(Z_STRVAL_PP(p_name) TSRMLS_CC);
-               if (tempmod) {
-                       if (PS(mod_data))
-                               PS(mod)->close(&PS(mod_data));
-                       PS(mod) = tempmod;
-                       PS(mod_data) = NULL;
-               } else {
-                       efree(old);
-                       php_error(E_ERROR, "Cannot find named PHP session module (%s)",
-                                       Z_STRVAL_PP(p_name));
+               if (!tempmod) {
+                       php_error(E_NOTICE, "Cannot find named PHP session module 
+(%s)",
+                                         Z_STRVAL_PP(p_name));
                        RETURN_FALSE;
                }
+               if (PS(mod_data))
+                       PS(mod)->close(&PS(mod_data) TSRMLS_CC);
+               PS(mod) = tempmod;
+               PS(mod_data) = NULL;
+               PS(rinit_mod) = 1;
        }
 
+       old = safe_estrdup(PS(mod)->name);
        RETVAL_STRING(old, 0);
 }
 /* }}} */
 
-/* {{{ proto void session_set_save_handler(string open, string close, string read, 
string write, string destroy, string gc)
+/* {{{ proto bool session_set_save_handler(string open, string close, string read, 
+string write, string destroy, string gc)
    Sets user-level functions */
 PHP_FUNCTION(session_set_save_handler)
 {
@@ -1099,8 +1123,13 @@
        if (ZEND_NUM_ARGS() != 6 || zend_get_parameters_array_ex(6, args) == FAILURE)
                WRONG_PARAM_COUNT;
        
-       if (PS(session_status) != php_session_none) 
+       if (PS(session_status) & PS_ACTIVE) {
+               php_error(E_NOTICE, "%s() cannot set session save handler functions 
+once session is started. "
+                                 "Current session save handler (%s)",
+                                 get_active_function_name(TSRMLS_C),
+                                 (PS(mod)->name ? PS(mod)->name : "none"));
                RETURN_FALSE;
+       }
        
        zend_alter_ini_entry("session.save_handler", sizeof("session.save_handler"), 
"user", sizeof("user")-1, PHP_INI_USER, PHP_INI_STAGE_RUNTIME);
 
@@ -1123,18 +1152,22 @@
 {
        zval **p_name;
        int ac = ZEND_NUM_ARGS();
-       char *old;
-
-       old = estrdup(PS(save_path));
+       char *old = NULL;
 
        if (ac < 0 || ac > 1 || zend_get_parameters_ex(ac, &p_name) == FAILURE)
                WRONG_PARAM_COUNT;
-
+       
        if (ac == 1) {
+               if (PS(session_status) & PS_ACTIVE) {
+                       php_error(E_NOTICE, "%s() cannot change session save path  
+once session is started.",
+                                         get_active_function_name(TSRMLS_C));
+                       RETURN_FALSE;
+               }
                convert_to_string_ex(p_name);
                zend_alter_ini_entry("session.save_path", sizeof("session.save_path"), 
Z_STRVAL_PP(p_name), Z_STRLEN_PP(p_name), PHP_INI_USER, PHP_INI_STAGE_RUNTIME);
        }
-       
+
+       old = estrdup(PS(save_path));
        RETVAL_STRING(old, 0);
 }
 /* }}} */
@@ -1147,18 +1180,21 @@
        int ac = ZEND_NUM_ARGS();
        char *old = empty_string;
 
-       if (PS(id))
-               old = estrdup(PS(id));
-
        if (ac < 0 || ac > 1 || zend_get_parameters_ex(ac, &p_name) == FAILURE)
                WRONG_PARAM_COUNT;
-
+       
        if (ac == 1) {
-               convert_to_string_ex(p_name);
                if (PS(id)) efree(PS(id));
+               if (PS(session_status) & PS_ACTIVE) {
+                       php_error(E_NOTICE, "%s() cannot set session id once session 
+is started.",
+                                         get_active_function_name(TSRMLS_C));
+                       RETURN_FALSE;
+               }
+               convert_to_string_ex(p_name);
                PS(id) = estrndup(Z_STRVAL_PP(p_name), Z_STRLEN_PP(p_name));
        }
-       
+
+       old = safe_estrdup(PS(id));
        RETVAL_STRING(old, 0);
 }
 /* }}} */
@@ -1169,18 +1205,23 @@
 {
        zval **p_cache_limiter;
        int ac = ZEND_NUM_ARGS();
-       char *old;
-
-       old = estrdup(PS(cache_limiter));
+       char *old = NULL;
 
        if (ac < 0 || ac > 1 || zend_get_parameters_ex(ac, &p_cache_limiter) == 
FAILURE)
                WRONG_PARAM_COUNT;
 
        if (ac == 1) {
+               if (PS(session_status) & (PS_ACTIVE|PS_ERROR)) {
+                       php_error(E_NOTICE, "%s() cannot set session module name once 
+session is started.",
+                                         get_active_function_name(TSRMLS_C));
+                       RETURN_FALSE;
+               }
+               
                convert_to_string_ex(p_cache_limiter);
                zend_alter_ini_entry("session.cache_limiter", 
sizeof("session.cache_limiter"), Z_STRVAL_PP(p_cache_limiter), 
Z_STRLEN_PP(p_cache_limiter), PHP_INI_USER, PHP_INI_STAGE_RUNTIME);
        }
-       
+
+       old = estrdup(PS(cache_limiter));
        RETVAL_STRING(old, 0);
 }
 /* }}} */
@@ -1191,9 +1232,7 @@
 {
        zval **p_cache_expire;
        int ac = ZEND_NUM_ARGS();
-       long old;
-
-       old = PS(cache_expire);
+       long old = PS(cache_expire);
 
        if (ac < 0 || ac > 1 || zend_get_parameters_ex(ac, &p_cache_expire) == FAILURE)
                WRONG_PARAM_COUNT;
@@ -1238,6 +1277,11 @@
        int      argc = ZEND_NUM_ARGS();
        int      i;
 
+       if (!PG(register_globals)) {
+               php_error(E_NOTICE, "Use %s() only for globals. Use $_SESSION, 
+instead.",
+                                 get_active_function_name(TSRMLS_C));
+       }
+       
        if (argc <= 0)
                RETURN_FALSE
        else
@@ -1248,7 +1292,7 @@
                WRONG_PARAM_COUNT;
        }
 
-       if (PS(session_status) == php_session_none)
+       if (PS(session_status) & PS_NONE)
                php_session_start(TSRMLS_C);
 
        for (i = 0; i < argc; i++) {
@@ -1270,9 +1314,20 @@
        zval **p_name;
        int ac = ZEND_NUM_ARGS();
 
+       if (!PG(register_globals)) {
+               php_error(E_NOTICE, "Use %s() only for globals. Use $_SESSION, 
+instead.",
+                                 get_active_function_name(TSRMLS_C));
+       }
+
        if (ac != 1 || zend_get_parameters_ex(ac, &p_name) == FAILURE)
                WRONG_PARAM_COUNT;
-       
+
+       if (!(PS(session_status) & PS_ACTIVE)) {
+               php_error(E_NOTICE, "%s() cannot be used unless session is started.",
+                                 get_active_function_name(TSRMLS_C));
+               RETURN_FALSE;
+       }
+               
        convert_to_string_ex(p_name);
        
        PS_DEL_VARL(Z_STRVAL_PP(p_name), Z_STRLEN_PP(p_name));
@@ -1289,9 +1344,20 @@
        zval *p_var;
        int ac = ZEND_NUM_ARGS();
 
+       if (!PG(register_globals)) {
+               php_error(E_NOTICE, "Use %s() only for globals. Use $_SESSION, 
+instead.",
+                                 get_active_function_name(TSRMLS_C));
+       }
+
        if (ac != 1 || zend_get_parameters_ex(ac, &p_name) == FAILURE)
                WRONG_PARAM_COUNT;
        
+       if (!(PS(session_status) & PS_ACTIVE)) {
+               php_error(E_NOTICE, "%s() cannot be used unless session is started.",
+                                 get_active_function_name(TSRMLS_C));
+               RETURN_FALSE;
+       }
+
        convert_to_string_ex(p_name);
        
        if (zend_hash_find(&PS(vars), Z_STRVAL_PP(p_name), 
@@ -1323,13 +1389,15 @@
 PHP_FUNCTION(session_decode)
 {
        zval **str;
+       int ret;
 
        if (ZEND_NUM_ARGS() != 1 || zend_get_parameters_ex(1, &str) == FAILURE)
                WRONG_PARAM_COUNT;
 
        convert_to_string_ex(str);
 
-       php_session_decode(Z_STRVAL_PP(str), Z_STRLEN_PP(str) TSRMLS_CC);
+       ret = php_session_decode(Z_STRVAL_PP(str), Z_STRLEN_PP(str) TSRMLS_CC);
+       RETURN_BOOL(ret);
 }
 /* }}} */
 
@@ -1337,7 +1405,11 @@
    Begin session - reinitializes freezed variables, registers browsers etc */
 PHP_FUNCTION(session_start)
 {
-       /* skipping check for non-zero args for performance reasons here ?*/
+       if (ZEND_NUM_ARGS() != 0) {
+               WRONG_PARAM_COUNT;
+       }
+
+       /* Session start may fail. Better to return status */
        php_session_start(TSRMLS_C);
        RETURN_TRUE;
 }
@@ -1360,7 +1432,7 @@
 /* }}} */
 
 
-/* {{{ proto void session_unset(void)
+/* {{{ proto bool session_unset(void)
    Unset all registered variables */
 PHP_FUNCTION(session_unset)
 {
@@ -1368,7 +1440,11 @@
        char     *variable;
        ulong     num_key;
        
-       if (PS(session_status) == php_session_none)
+       if (ZEND_NUM_ARGS() != 0) {
+               WRONG_PARAM_COUNT;
+       }
+
+       if (PS(session_status) & PS_NONE)
                RETURN_FALSE;
 
        if (PG(register_globals)) {
@@ -1383,13 +1459,14 @@
 
        /* Clean $HTTP_SESSION_VARS. */
        zend_hash_clean(Z_ARRVAL_P(PS(http_session_vars)));
+       RETURN_TRUE;
 }
 /* }}} */
 
 
 PHPAPI void session_adapt_url(const char *url, size_t urllen, char **new, size_t 
*newlen TSRMLS_DC)
 {
-       if (PS(apply_trans_sid) && (PS(session_status) == php_session_active)) {
+       if (PS(apply_trans_sid) && (PS(session_status) & PS_ACTIVE)) {
                *new = url_adapt_single_url(url, urllen, PS(session_name), PS(id), 
newlen TSRMLS_CC);
        }
 }
@@ -1399,7 +1476,7 @@
 {              
        zend_hash_init(&PS(vars), 0, NULL, NULL, 0);
        PS(id) = NULL;
-       PS(session_status) = php_session_none;
+       PS(session_status) = PS_NONE;
        PS(mod_data) = NULL;
        PS(output_handler_registered) = 0;
 }
@@ -1407,10 +1484,10 @@
 static void php_rshutdown_session_globals(TSRMLS_D)
 {
        if (PS(mod_data)) {
-               PS(mod)->close(&PS(mod_data));
+               PS(mod)->close(&PS(mod_data) TSRMLS_CC);
        }
        if (PS(id)) {
-               efree(PS(id));
+               efree(PS(id) TSRMLS_CC);
        }
        zend_hash_destroy(&PS(vars));
 }
@@ -1420,8 +1497,9 @@
 {
        php_rinit_session_globals(TSRMLS_C);
 
-       if (PS(mod) == NULL) {
+       if (PS(mod) == NULL || PS(rinit_mod)) {
                char *value;
+               PS(rinit_mod) = 0;
 
                value = zend_ini_string("session.save_handler", 
sizeof("session.save_handler"), 0);
                if (value) {
@@ -1430,7 +1508,7 @@
 
                if (!PS(mod)) {
                        /* current status is unusable */
-                       PS(session_status) = php_session_disabled;
+                       PS(session_status) = PS_DISABLED;
                        return SUCCESS;
                }
        }
@@ -1444,9 +1522,9 @@
 
 static void php_session_flush(TSRMLS_D)
 {
-       if(PS(session_status)==php_session_active) {
+       if(PS(session_status) & PS_ACTIVE) {
                php_session_save_current_state(TSRMLS_C);
-               PS(session_status)=php_session_none;
+               PS(session_status) = PS_DISABLED;
        }
 }
 
@@ -1462,8 +1540,10 @@
        if (PS(output_handler_registered)) {
                php_session_end_output_handler(TSRMLS_C);
        }
-       php_session_flush(TSRMLS_C);
+       if (PS(session_status) & PS_ACTIVE)
+               php_session_flush(TSRMLS_C);
        php_rshutdown_session_globals(TSRMLS_C);
+       PS(session_status) = PS_DISABLED;
        return SUCCESS;
 }
 /* }}} */
Index: ext/standard/basic_functions.c
===================================================================
RCS file: /repository/php4/ext/standard/basic_functions.c,v
retrieving revision 1.442
diff -u -r1.442 basic_functions.c
--- ext/standard/basic_functions.c      10 Feb 2002 17:38:15 -0000      1.442
+++ ext/standard/basic_functions.c      16 Feb 2002 05:34:03 -0000
@@ -733,6 +733,7 @@
        PHP_FE(ob_end_clean,                                                           
                                         NULL)
        PHP_FE(ob_get_length,                                                          
                                         NULL)
        PHP_FE(ob_get_level,                                                           
                                         NULL)
+       PHP_FE(ob_get_status,                                                          
+                                         NULL)
        PHP_FE(ob_get_contents,                                                        
                                         NULL)
        PHP_FE(ob_implicit_flush,                                                      
                                         NULL)
 
@@ -1863,7 +1864,7 @@
        convert_to_string(filename);
 
        if (i) {
-               php_start_ob_buffer (NULL, 0 TSRMLS_CC);
+               php_start_ob_buffer (NULL, 0, 1 TSRMLS_CC);
        }
 
        php_get_highlight_struct(&syntax_highlighter_ini);
@@ -1896,7 +1897,7 @@
        convert_to_string(expr);
 
        if (i) {
-               php_start_ob_buffer (NULL, 0 TSRMLS_CC);
+               php_start_ob_buffer (NULL, 0, 1 TSRMLS_CC);
        }
 
        php_get_highlight_struct(&syntax_highlighter_ini);
Index: ext/standard/var.c
===================================================================
RCS file: /repository/php4/ext/standard/var.c,v
retrieving revision 1.127
diff -u -r1.127 var.c
--- ext/standard/var.c  10 Feb 2002 17:38:15 -0000      1.127
+++ ext/standard/var.c  16 Feb 2002 05:34:04 -0000
@@ -312,7 +312,7 @@
        }
        
        if (i) {
-               php_start_ob_buffer (NULL, 0 TSRMLS_CC);
+               php_start_ob_buffer (NULL, 0, 1 TSRMLS_CC);
        }
        
        php_var_export(&var, 1 TSRMLS_CC);
Index: ext/zlib/zlib.c
===================================================================
RCS file: /repository/php4/ext/zlib/zlib.c,v
retrieving revision 1.105
diff -u -r1.105 zlib.c
--- ext/zlib/zlib.c     11 Dec 2001 15:30:59 -0000      1.105
+++ ext/zlib/zlib.c     16 Feb 2002 05:34:06 -0000
@@ -1283,8 +1283,8 @@
                return FAILURE;
        }
        
-       php_start_ob_buffer(NULL, buffer_size TSRMLS_CC);
-       php_ob_set_internal_handler(php_gzip_output_handler, buffer_size*1.5 
TSRMLS_CC);
+       php_start_ob_buffer(NULL, buffer_size, 0 TSRMLS_CC);
+       php_ob_set_internal_handler(php_gzip_output_handler, buffer_size*1.5, "zlib 
+output compression", 0 TSRMLS_CC);
        return SUCCESS;
 }
 /* }}} */
Index: main/main.c
===================================================================
RCS file: /repository/php4/main/main.c,v
retrieving revision 1.422
diff -u -r1.422 main.c
--- main/main.c 14 Feb 2002 20:16:05 -0000      1.422
+++ main/main.c 16 Feb 2002 05:34:07 -0000
@@ -669,14 +669,17 @@
                        Z_STRLEN_P(output_handler) = strlen(PG(output_handler));       
 /* this can be optimized */
                        Z_STRVAL_P(output_handler) = estrndup(PG(output_handler), 
Z_STRLEN_P(output_handler));
                        Z_TYPE_P(output_handler) = IS_STRING;
-                       php_start_ob_buffer(output_handler, 0 TSRMLS_CC);
-               } else if (PG(output_buffering)) {
+                       php_start_ob_buffer(output_handler, 0, 1 TSRMLS_CC);
+               }
+               else if (PG(output_buffering)) {
                        if (PG(output_buffering)>1) {
-                               php_start_ob_buffer(NULL, PG(output_buffering) 
TSRMLS_CC);
-                       } else {
-                               php_start_ob_buffer(NULL, 0 TSRMLS_CC);
+                               php_start_ob_buffer(NULL, PG(output_buffering), 1 
+TSRMLS_CC);
                        }
-               } else if (PG(implicit_flush)) {
+                       else {
+                               php_start_ob_buffer(NULL, 0, 1 TSRMLS_CC);
+                       }
+               }
+               else if (PG(implicit_flush)) {
                        php_start_implicit_flush(TSRMLS_C);
                }
 
Index: main/output.c
===================================================================
RCS file: /repository/php4/main/output.c,v
retrieving revision 1.84
diff -u -r1.84 output.c
--- main/output.c       7 Feb 2002 02:50:28 -0000       1.84
+++ main/output.c       16 Feb 2002 05:34:07 -0000
@@ -29,7 +29,7 @@
 static int php_ub_body_write_no_header(const char *str, uint str_length TSRMLS_DC);
 static int php_b_body_write(const char *str, uint str_length TSRMLS_DC);
 
-static void php_ob_init(uint initial_size, uint block_size, zval *output_handler, 
uint chunk_size TSRMLS_DC);
+static void php_ob_init(uint initial_size, uint block_size, zval *output_handler, 
+uint chunk_size, zend_bool erase TSRMLS_DC);
 static void php_ob_append(const char *text, uint text_length TSRMLS_DC);
 #if 0
 static void php_ob_prepend(const char *text, uint text_length);
@@ -110,15 +110,15 @@
 
 /* {{{ php_start_ob_buffer
  * Start output buffering */
-PHPAPI int php_start_ob_buffer(zval *output_handler, uint chunk_size TSRMLS_DC)
+PHPAPI int php_start_ob_buffer(zval *output_handler, uint chunk_size, zend_bool erase 
+TSRMLS_DC)
 {
        if (OG(ob_lock)) {
                return FAILURE;
        }
        if (chunk_size) {
-               php_ob_init((chunk_size*3/2), chunk_size/2, output_handler, chunk_size 
TSRMLS_CC);
+               php_ob_init((chunk_size*3/2), chunk_size/2, output_handler, 
+chunk_size, erase TSRMLS_CC);
        } else {
-               php_ob_init(40*1024, 10*1024, output_handler, chunk_size TSRMLS_CC);
+               php_ob_init(40*1024, 10*1024, output_handler, chunk_size, erase 
+TSRMLS_CC);
        }
        OG(php_body_write) = php_b_body_write;
        return SUCCESS;
@@ -185,6 +185,7 @@
                        orig_buffer->refcount-=2;
                }
                zval_ptr_dtor(&z_status);
+               zval_ptr_dtor(&OG(active_ob_buffer).output_handler);
        }
 
        if (!final_buffer) {
@@ -283,7 +284,7 @@
 
 /* {{{ php_ob_set_internal_handler
  */
-PHPAPI void php_ob_set_internal_handler(php_output_handler_func_t 
internal_output_handler, uint buffer_size TSRMLS_DC)
+PHPAPI void php_ob_set_internal_handler(php_output_handler_func_t 
+internal_output_handler, uint buffer_size, char *handler_name, zend_bool erase 
+TSRMLS_DC)
 {
        if (OG(ob_nesting_level)==0) {
                return;
@@ -292,6 +293,8 @@
        OG(active_ob_buffer).internal_output_handler = internal_output_handler;
        OG(active_ob_buffer).internal_output_handler_buffer = (char *) 
emalloc(buffer_size);
        OG(active_ob_buffer).internal_output_handler_buffer_size = buffer_size;
+       OG(active_ob_buffer).handler_name = handler_name;
+       OG(active_ob_buffer).erase = erase;     
 }
 /* }}} */
 
@@ -315,7 +318,7 @@
 
 /* {{{ php_ob_init
  */
-static void php_ob_init(uint initial_size, uint block_size, zval *output_handler, 
uint chunk_size TSRMLS_DC)
+static void php_ob_init(uint initial_size, uint block_size, zval *output_handler, 
+uint chunk_size, zend_bool erase TSRMLS_DC)
 {
        if (OG(ob_nesting_level)>0) {
                if (OG(ob_nesting_level)==1) { /* initialize stack */
@@ -332,6 +335,18 @@
        OG(active_ob_buffer).chunk_size = chunk_size;
        OG(active_ob_buffer).status = 0;
        OG(active_ob_buffer).internal_output_handler = NULL;
+       if (output_handler && output_handler->type == IS_STRING) {
+               OG(active_ob_buffer).handler_name = Z_STRVAL_P(output_handler);
+       }
+       else if (output_handler && output_handler->type == IS_ARRAY) {
+               /* FIXME: Array type is not supported yet.
+                  See call_user_function_ex() for detials. */
+               OG(active_ob_buffer).handler_name = "array is not supported yet";
+       }
+       else {
+               OG(active_ob_buffer).handler_name = "default output handler";
+       }
+       OG(active_ob_buffer).erase = erase;     
 }
 /* }}} */
 
@@ -478,47 +493,24 @@
  * HEAD support
  */
 
-/* {{{ proto void ob_start([ string user_function [, int chunk_size]])
+/* {{{ proto void ob_start([ string user_function [, int chunk_size [, bool erase]]])
    Turn on Output Buffering (specifying an optional output handler). */
 PHP_FUNCTION(ob_start)
 {
        zval *output_handler=NULL;
        uint chunk_size=0;
+       zend_bool erase=1;
+       int argc = ZEND_NUM_ARGS();
+       
+       if (zend_parse_parameters(argc TSRMLS_CC, "|zlb", &output_handler, 
+                                                         &chunk_size, &erase) == 
+FAILURE)
+               return;
 
-       switch (ZEND_NUM_ARGS()) {
-               case 0:
-                       break;
-               case 1: {
-                               zval **output_handler_p;
-
-                               if (zend_get_parameters_ex(1, 
&output_handler_p)==FAILURE) {
-                                       RETURN_FALSE;
-                               }
-                               SEPARATE_ZVAL(output_handler_p);
-                               output_handler = *output_handler_p;
-                               output_handler->refcount++;
-                       }
-                       break;
-               case 2: {
-                               zval **output_handler_p, **chunk_size_p;
-
-                               if (zend_get_parameters_ex(2, &output_handler_p, 
&chunk_size_p)==FAILURE) {
-                                       RETURN_FALSE;
-                               }
-                               if (Z_STRLEN_PP(output_handler_p)>0) {
-                                       SEPARATE_ZVAL(output_handler_p);
-                                       output_handler = *output_handler_p;
-                                       output_handler->refcount++;
-                               }
-                               convert_to_long_ex(chunk_size_p);
-                               chunk_size = (uint) Z_LVAL_PP(chunk_size_p);
-                       }
-                       break;
-               default:
-                       ZEND_WRONG_PARAM_COUNT();
-                       break;
-       }
-       if (php_start_ob_buffer(output_handler, chunk_size TSRMLS_CC)==FAILURE) {
+       if (output_handler) {
+               SEPARATE_ZVAL(&output_handler);
+               output_handler->refcount++;
+       }       
+       if (php_start_ob_buffer(output_handler, chunk_size, erase TSRMLS_CC)==FAILURE) 
+{
                if (SG(headers_sent) && !SG(request_info).headers_only) {
                        OG(php_body_write) = php_ub_body_write_no_header;
                } else {
@@ -532,47 +524,91 @@
 }
 /* }}} */
 
-/* {{{ proto void ob_flush(void)
-   Flush (send) the output buffer */
+/* {{{ proto bool ob_flush(void)
+   Flush (send) contents of the output buffers */
 PHP_FUNCTION(ob_flush)
 {
        if (ZEND_NUM_ARGS() != 0)
                        WRONG_PARAM_COUNT;
+
+       if (!OG(ob_nesting_level)) {
+               php_error(E_NOTICE, "%s() failed to flush buffer. No buffer to flush.",
+                                 get_active_function_name(TSRMLS_C));
+               RETURN_FALSE;
+       }
                
        php_end_ob_buffer(1, 1 TSRMLS_CC);
+       RETURN_TRUE;
 }
 /* }}} */
 
-/* {{{ proto void ob_clean(void)
-   Clean (erase) the output buffer */
+/* {{{ proto bool ob_clean(void)
+   Clean (delete) the current output buffer */
 PHP_FUNCTION(ob_clean)
 {
        if (ZEND_NUM_ARGS() != 0)
                        WRONG_PARAM_COUNT;
-               
+
+       
+       if (!OG(ob_nesting_level)) {
+               php_error(E_NOTICE, "%s() failed to delete buffer. No buffer to 
+delete.",
+                                 get_active_function_name(TSRMLS_C));
+               RETURN_FALSE;
+       }
+       if (OG(ob_nesting_level) && !OG(active_ob_buffer).status && 
+!OG(active_ob_buffer).erase) {
+               php_error(E_NOTICE, "%s() failed to delete buffer %s.",
+                                 get_active_function_name(TSRMLS_C), 
+OG(active_ob_buffer).handler_name);
+               RETURN_FALSE;
+       }
+       
        php_end_ob_buffer(0, 1 TSRMLS_CC);
+       RETURN_TRUE;
 }
 /* }}} */
 
-/* {{{ proto void ob_end_flush(void)
-   Flush (send) the output buffer, and turn off output buffering */
+/* {{{ proto bool ob_end_flush(void)
+   Flush (send) the output buffer, and delete current output buffer */
 PHP_FUNCTION(ob_end_flush)
 {
        if (ZEND_NUM_ARGS() != 0)
                        WRONG_PARAM_COUNT;
-               
+       
+       if (!OG(ob_nesting_level)) {
+               php_error(E_NOTICE, "%s() failed to delete and flush buffer. No buffer 
+to delete or flush.",
+                                 get_active_function_name(TSRMLS_C));
+               RETURN_FALSE;
+       }
+       if (OG(ob_nesting_level) && !OG(active_ob_buffer).status && 
+!OG(active_ob_buffer).erase) {
+               php_error(E_NOTICE, "%s() failed to delete buffer %s.",
+                                 get_active_function_name(TSRMLS_C), 
+OG(active_ob_buffer).handler_name);
+               RETURN_FALSE;
+       }
+       
        php_end_ob_buffer(1, 0 TSRMLS_CC);
+       RETURN_TRUE;
 }
 /* }}} */
 
-/* {{{ proto void ob_end_clean(void)
-   Clean (erase) the output buffer, and turn off output buffering */
+/* {{{ proto bool ob_end_clean(void)
+   Clean the output buffer, and delete current output buffer */
 PHP_FUNCTION(ob_end_clean)
 {
        if (ZEND_NUM_ARGS() != 0)
                        WRONG_PARAM_COUNT;
                
+       if (!OG(ob_nesting_level)) {
+               php_error(E_NOTICE, "%s() failed to delete buffer. No buffer to 
+delete.",
+                                 get_active_function_name(TSRMLS_C));
+               RETURN_FALSE;
+       }
+       if (OG(ob_nesting_level) && !OG(active_ob_buffer).status && 
+!OG(active_ob_buffer).erase) {
+               php_error(E_NOTICE, "%s() failed to delete buffer %s.",
+                                 get_active_function_name(TSRMLS_C), 
+OG(active_ob_buffer).handler_name);
+               RETURN_FALSE;
+       }
+       
        php_end_ob_buffer(0, 0 TSRMLS_CC);
+       RETURN_TRUE;
 }
 /* }}} */
 
@@ -612,6 +648,79 @@
        }
 }
 /* }}} */
+
+static int php_ob_buffer_status(php_ob_buffer *ob_buffer, zval *result) 
+{
+       zval *elem;
+
+       MAKE_STD_ZVAL(elem);
+       if (array_init(elem))
+               return FAILURE;
+       
+       if (ob_buffer->internal_output_handler) {
+               add_assoc_long(elem, "type", PHP_OUTPUT_HANDLER_INTERNAL);
+       }
+       else {
+               add_assoc_long(elem, "type", PHP_OUTPUT_HANDLER_USER);
+       }
+       add_assoc_long(elem, "status", ob_buffer->status);
+       add_assoc_string(elem, "name", ob_buffer->handler_name, 1);
+       add_assoc_bool(elem, "del", ob_buffer->erase);
+       add_next_index_zval(result, elem);
+
+       return SUCCESS;
+}
+
+
+/* {{{ poto array ob_get_status([bool full_status])
+   Return the nesting level of the output buffer */
+PHP_FUNCTION(ob_get_status)
+{
+       int argc = ZEND_NUM_ARGS();
+       zend_bool full_status = 0;
+       
+       if (zend_parse_parameters(argc TSRMLS_CC, "|b", &full_status) == FAILURE )
+                       return;
+       
+       if (array_init(return_value) == FAILURE) {
+               RETURN_FALSE;
+       }
+
+       if (full_status) {
+               zval *elem;
+
+               zend_stack_apply_with_argument(&OG(ob_buffers), 
+ZEND_STACK_APPLY_BOTTOMUP, (int (*)(void *elem, void *))php_ob_buffer_status, 
+return_value);
+
+               MAKE_STD_ZVAL(elem);
+               if (array_init(elem))
+                       RETURN_FALSE;
+       
+               if (OG(active_ob_buffer).internal_output_handler) {
+                       add_assoc_long(elem, "type", PHP_OUTPUT_HANDLER_INTERNAL);
+               }
+               else {
+                       add_assoc_long(elem, "type", PHP_OUTPUT_HANDLER_USER);
+               }
+               add_assoc_long(elem, "status", OG(active_ob_buffer).status);
+               add_assoc_string(elem, "name", OG(active_ob_buffer).handler_name, 1);
+               add_assoc_bool(elem, "del", OG(active_ob_buffer).erase);
+               add_next_index_zval(return_value, elem);
+       }
+       else {
+               add_assoc_long(return_value, "level", OG(ob_nesting_level));
+               if (OG(active_ob_buffer).internal_output_handler) {
+                       add_assoc_long(return_value, "type", 
+PHP_OUTPUT_HANDLER_INTERNAL);
+               }
+               else {
+                       add_assoc_long(return_value, "type", PHP_OUTPUT_HANDLER_USER);
+               }
+               add_assoc_long(return_value, "status", OG(active_ob_buffer).status);
+               add_assoc_string(return_value, "name", 
+OG(active_ob_buffer).handler_name, 1);
+               add_assoc_bool(return_value, "del", OG(active_ob_buffer).erase);
+       }
+}
+/* }}} */
+
 
 /* {{{ proto void ob_implicit_flush([int flag])
    Turn implicit flush on/off and is equivalent to calling flush() after every output 
call */
Index: main/php_output.h
===================================================================
RCS file: /repository/php4/main/php_output.h,v
retrieving revision 1.34
diff -u -r1.34 php_output.h
--- main/php_output.h   11 Dec 2001 15:31:04 -0000      1.34
+++ main/php_output.h   16 Feb 2002 05:34:07 -0000
@@ -29,7 +29,7 @@
 void php_output_register_constants(TSRMLS_D);
 PHPAPI int  php_body_write(const char *str, uint str_length TSRMLS_DC);
 PHPAPI int  php_header_write(const char *str, uint str_length TSRMLS_DC);
-PHPAPI int php_start_ob_buffer(zval *output_handler, uint chunk_size TSRMLS_DC);
+PHPAPI int php_start_ob_buffer(zval *output_handler, uint chunk_size, zend_bool erase 
+TSRMLS_DC);
 PHPAPI void php_end_ob_buffer(zend_bool send_buffer, zend_bool just_flush TSRMLS_DC);
 PHPAPI void php_end_ob_buffers(zend_bool send_buffer TSRMLS_DC);
 PHPAPI int php_ob_get_buffer(zval *p TSRMLS_DC);
@@ -38,7 +38,7 @@
 PHPAPI void php_end_implicit_flush(TSRMLS_D);
 PHPAPI char *php_get_output_start_filename(TSRMLS_D);
 PHPAPI int php_get_output_start_lineno(TSRMLS_D);
-PHPAPI void php_ob_set_internal_handler(php_output_handler_func_t 
internal_output_handler, uint buffer_size TSRMLS_DC);
+PHPAPI void php_ob_set_internal_handler(php_output_handler_func_t 
+internal_output_handler, uint buffer_size, char *handler_name, zend_bool erase 
+TSRMLS_DC);
 
 PHP_FUNCTION(ob_start);
 PHP_FUNCTION(ob_flush);
@@ -48,6 +48,7 @@
 PHP_FUNCTION(ob_get_contents);
 PHP_FUNCTION(ob_get_length);
 PHP_FUNCTION(ob_get_level);
+PHP_FUNCTION(ob_get_status);
 PHP_FUNCTION(ob_implicit_flush);
 
 typedef struct _php_ob_buffer {
@@ -61,6 +62,8 @@
        php_output_handler_func_t internal_output_handler;
        char *internal_output_handler_buffer;
        uint internal_output_handler_buffer_size;
+       char *handler_name;
+       zend_bool erase;
 } php_ob_buffer;
 
 typedef struct _php_output_globals {
@@ -76,7 +79,6 @@
        zend_bool disable_output;
 } php_output_globals;
 
-
 #ifdef ZTS
 #define OG(v) TSRMG(output_globals_id, php_output_globals *, v)
 ZEND_API extern int output_globals_id;
@@ -88,5 +90,9 @@
 #define PHP_OUTPUT_HANDLER_START               (1<<0)
 #define PHP_OUTPUT_HANDLER_CONT                        (1<<1)
 #define PHP_OUTPUT_HANDLER_END                 (1<<2)
+
+#define PHP_OUTPUT_HANDLER_INTERNAL     0
+#define PHP_OUTPUT_HANDLER_USER        1
+
 
 #endif /* PHP_OUTPUT_H */

-- 
PHP Development Mailing List <http://www.php.net/>
To unsubscribe, visit: http://www.php.net/unsub.php

Reply via email to