Commit:    554021d21e1b2517313a377676260c188152c2eb
Author:    Yasuo Ohgaki <yohg...@php.net>         Sat, 10 Aug 2013 13:56:32 
+0900
Parents:   678ec306557f61bf54b6df454387e7d9c3f50de5
Branches:  master

Link:       
http://git.php.net/?p=php-src.git;a=commitdiff;h=554021d21e1b2517313a377676260c188152c2eb

Log:
Implemented Bug #17860 Suggestion: auto detect whether session changed

Bugs:
https://bugs.php.net/17860

Changed paths:
  M  NEWS
  M  ext/session/php_session.h
  M  ext/session/session.c
  M  ext/session/tests/session_set_save_handler_basic.phpt
  M  ext/session/tests/session_set_save_handler_class_003.phpt
  M  ext/session/tests/session_set_save_handler_class_007.phpt
  M  ext/session/tests/session_set_save_handler_closures.phpt
  A  ext/session/tests/session_set_save_handler_write_short_circuit.phpt

diff --git a/NEWS b/NEWS
index f9cb504..b444b44 100644
--- a/NEWS
+++ b/NEWS
@@ -11,6 +11,7 @@ PHP                                                           
             NEWS
   . Fixed Bug #65315 (session.hash_function silently fallback to default md5)
     (Yasuo)
   . Implemented Request #54649 (Create session_serializer_name()). (Yasuo)
+  . Implemented Request #17860 (Session write short circuit). (Yasuo)
 
 - mysqlnd:
   . Disabled flag for SP OUT variables for 5.5+ servers as they are not 
natively
diff --git a/ext/session/php_session.h b/ext/session/php_session.h
index e8e79f0..ba3420e 100644
--- a/ext/session/php_session.h
+++ b/ext/session/php_session.h
@@ -180,6 +180,7 @@ typedef struct _php_ps_globals {
        double rfc1867_min_freq;   /* session.upload_progress.min_freq */
 
        zend_bool use_strict_mode; /* whether or not PHP accepts unknown 
session ids */
+       char session_data_hash[16]; /* binary MD5 hash length */
 } php_ps_globals;
 
 typedef php_ps_globals zend_ps_globals;
diff --git a/ext/session/session.c b/ext/session/session.c
index 278f954..24299b7 100644
--- a/ext/session/session.c
+++ b/ext/session/session.c
@@ -505,8 +505,17 @@ static void php_session_initialize(TSRMLS_D) /* {{{ */
                */
        }
        if (val) {
+               PHP_MD5_CTX context;
+
+               /* Store read data's MD5 hash */
+               PHP_MD5Init(&context);
+               PHP_MD5Update(&context, val, vallen);
+               PHP_MD5Final(PS(session_data_hash), &context);
+
                php_session_decode(val, vallen TSRMLS_CC);
                efree(val);
+       } else {
+                       memset(PS(session_data_hash),'\0', 16);
        }
 
        if (!PS(use_cookies) && PS(send_cookie)) {
@@ -529,7 +538,20 @@ static void php_session_save_current_state(TSRMLS_D) /* 
{{{ */
 
                        val = php_session_encode(&vallen TSRMLS_CC);
                        if (val) {
-                               ret = PS(mod)->s_write(&PS(mod_data), PS(id), 
val, vallen TSRMLS_CC);
+                               PHP_MD5_CTX context;
+                               unsigned char digest[16];
+                               char md5_hash[33];
+
+                               /* Generate data's MD5 hash */
+                               PHP_MD5Init(&context);
+                               PHP_MD5Update(&context, val, vallen);
+                               PHP_MD5Final(digest, &context);
+                               /* Write only when save is required */
+                               if (memcmp(digest, PS(session_data_hash), 16)) {
+                                       ret = PS(mod)->s_write(&PS(mod_data), 
PS(id), val, vallen TSRMLS_CC);
+                               } else {
+                                       ret = SUCCESS;
+                               }
                                efree(val);
                        } else {
                                ret = PS(mod)->s_write(&PS(mod_data), PS(id), 
"", 0 TSRMLS_CC);
diff --git a/ext/session/tests/session_set_save_handler_basic.phpt 
b/ext/session/tests/session_set_save_handler_basic.phpt
index 3897ba9..e8496e8 100644
--- a/ext/session/tests/session_set_save_handler_basic.phpt
+++ b/ext/session/tests/session_set_save_handler_basic.phpt
@@ -43,6 +43,7 @@ session_id($session_id);
 session_set_save_handler("open", "close", "read", "write", "destroy", "gc");
 session_start();
 var_dump($_SESSION);
+$_SESSION['Bar'] = 'Foo';
 session_write_close();
 
 ob_end_flush();
@@ -91,5 +92,5 @@ array(3) {
   ["Guff"]=>
   int(1234567890)
 }
-Write [%s,%s,Blah|s:12:"Hello World!";Foo|b:0;Guff|i:1234567890;]
+Write [%s,%s,Blah|s:12:"Hello World!";Foo|b:0;Guff|i:1234567890;Bar|s:3:"Foo";]
 Close [%s,PHPSESSID]
diff --git a/ext/session/tests/session_set_save_handler_class_003.phpt 
b/ext/session/tests/session_set_save_handler_class_003.phpt
index e9a3cc2..29b3846 100644
--- a/ext/session/tests/session_set_save_handler_class_003.phpt
+++ b/ext/session/tests/session_set_save_handler_class_003.phpt
@@ -58,6 +58,7 @@ session_set_save_handler($handler);
 
 session_start();
 
+$_SESSION['bar'] = 'hello';
 session_write_close();
 session_unset();
 
@@ -71,8 +72,10 @@ array(1) {
 }
 int(4)
 string(%d) "%s"
-array(1) {
+array(2) {
   ["foo"]=>
   string(5) "hello"
+  ["bar"]=>
+  string(5) "hello"
 }
 string(3) "hai"
diff --git a/ext/session/tests/session_set_save_handler_class_007.phpt 
b/ext/session/tests/session_set_save_handler_class_007.phpt
index 7344ae1..55f7225 100644
--- a/ext/session/tests/session_set_save_handler_class_007.phpt
+++ b/ext/session/tests/session_set_save_handler_class_007.phpt
@@ -56,6 +56,7 @@ $handler = new MySession(2);
 session_set_save_handler($handler);
 session_start();
 
+$_SESSION['abc'] = 'xyz';
 // implicit close (called by shutdown function)
 echo "done\n";
 ob_end_flush();
@@ -69,6 +70,6 @@ ob_end_flush();
 (#2) constructor called
 (#1) destructor called
 done
-(#2) writing %s = foo|s:3:"bar";
+(#2) writing %s = foo|s:3:"bar";abc|s:3:"xyz";
 (#2) closing %s
 (#2) destructor called
diff --git a/ext/session/tests/session_set_save_handler_closures.phpt 
b/ext/session/tests/session_set_save_handler_closures.phpt
index 21b2c68..1251886 100644
--- a/ext/session/tests/session_set_save_handler_closures.phpt
+++ b/ext/session/tests/session_set_save_handler_closures.phpt
@@ -42,6 +42,7 @@ echo "Starting session again..!\n";
 session_id($session_id);
 session_set_save_handler($open_closure, $close_closure, $read_closure, 
$write_closure, $destroy_closure, $gc_closure);
 session_start();
+$_SESSION['Bar'] = 'Foo';
 var_dump($_SESSION);
 session_write_close();
 
@@ -83,13 +84,15 @@ array(3) {
 Starting session again..!
 Open [%s,PHPSESSID]
 Read [%s,%s]
-array(3) {
+array(4) {
   ["Blah"]=>
   string(12) "Hello World!"
   ["Foo"]=>
   bool(false)
   ["Guff"]=>
   int(1234567890)
+  ["Bar"]=>
+  string(3) "Foo"
 }
-Write [%s,%s,Blah|s:12:"Hello World!";Foo|b:0;Guff|i:1234567890;]
+Write [%s,%s,Blah|s:12:"Hello World!";Foo|b:0;Guff|i:1234567890;Bar|s:3:"Foo";]
 Close [%s,PHPSESSID]
diff --git 
a/ext/session/tests/session_set_save_handler_write_short_circuit.phpt 
b/ext/session/tests/session_set_save_handler_write_short_circuit.phpt
new file mode 100644
index 0000000..02ca182
--- /dev/null
+++ b/ext/session/tests/session_set_save_handler_write_short_circuit.phpt
@@ -0,0 +1,104 @@
+--TEST--
+Test session_set_save_handler() function : test write short circuit
+--INI--
+session.save_path=
+session.name=PHPSESSID
+--SKIPIF--
+<?php include('skipif.inc'); ?>
+--FILE--
+<?php
+
+ob_start();
+
+/*
+ * Prototype : bool session_set_save_handler(callback $open, callback $close, 
callback $read, callback $write, callback $destroy, callback $gc)
+ * Description : Sets user-level session storage functions
+ * Source code : ext/session/session.c
+ */
+
+echo "*** Testing session_set_save_handler() : test write short circuit ***\n";
+
+require_once "save_handler.inc";
+$path = dirname(__FILE__);
+session_save_path($path);
+session_set_save_handler("open", "close", "read", "write", "destroy", "gc");
+
+session_start();
+$session_id = session_id();
+$_SESSION["Blah"] = "Hello World!";
+$_SESSION["Foo"] = FALSE;
+$_SESSION["Guff"] = 1234567890;
+var_dump($_SESSION);
+
+session_write_close();
+session_unset();
+var_dump($_SESSION);
+
+echo "Starting session again..!\n";
+session_id($session_id);
+session_set_save_handler("open", "close", "read", "write", "destroy", "gc");
+session_start();
+var_dump($_SESSION);
+$_SESSION['Bar'] = 'Foo';
+session_write_close();
+
+echo "Starting session again..!\n";
+session_id($session_id);
+session_set_save_handler("open", "close", "read", "write", "destroy", "gc");
+session_start();
+var_dump($_SESSION);
+// $_SESSION should be the same and should skip write()
+session_write_close();
+
+ob_end_flush();
+?>
+--EXPECTF--
+*** Testing session_set_save_handler() : test write short circuit ***
+
+Open [%s,PHPSESSID]
+Read [%s,%s]
+array(3) {
+  ["Blah"]=>
+  string(12) "Hello World!"
+  ["Foo"]=>
+  bool(false)
+  ["Guff"]=>
+  int(1234567890)
+}
+Write [%s,%s,Blah|s:12:"Hello World!";Foo|b:0;Guff|i:1234567890;]
+Close [%s,PHPSESSID]
+array(3) {
+  ["Blah"]=>
+  string(12) "Hello World!"
+  ["Foo"]=>
+  bool(false)
+  ["Guff"]=>
+  int(1234567890)
+}
+Starting session again..!
+Open [%s,PHPSESSID]
+Read [%s,%s]
+array(3) {
+  ["Blah"]=>
+  string(12) "Hello World!"
+  ["Foo"]=>
+  bool(false)
+  ["Guff"]=>
+  int(1234567890)
+}
+Write [%s,%s,Blah|s:12:"Hello World!";Foo|b:0;Guff|i:1234567890;Bar|s:3:"Foo";]
+Close [%s,PHPSESSID]
+Starting session again..!
+Open [%s,PHPSESSID]
+Read [%s,%s]
+array(4) {
+  ["Blah"]=>
+  string(12) "Hello World!"
+  ["Foo"]=>
+  bool(false)
+  ["Guff"]=>
+  int(1234567890)
+  ["Bar"]=>
+  string(3) "Foo"
+}
+Close [%s,PHPSESSID]
\ No newline at end of file
-- 
PHP CVS Mailing List (http://www.php.net/)
To unsubscribe, visit: http://www.php.net/unsub.php

Reply via email to