summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAleksander Machniak <alec@alec.pl>2013-06-02 14:33:11 +0200
committerAleksander Machniak <alec@alec.pl>2013-06-02 14:46:36 +0200
commit72c8504b99fbd423651bab0180a044c489ca05cc (patch)
treed7903d6e17aacbee1637642a0530bb8ea9e7a6ee
parent6213c6a6e18848d861f2add83bdb69a1de3f5956 (diff)
Fix bug where serialized strings were truncated in PDO::quote() (#1489142)
Conflicts: CHANGELOG program/lib/Roundcube/rcube_cache_shared.php
-rw-r--r--CHANGELOG1
-rw-r--r--program/lib/Roundcube/rcube_cache.php33
-rw-r--r--program/lib/Roundcube/rcube_db.php23
-rw-r--r--program/lib/Roundcube/rcube_imap_cache.php12
4 files changed, 54 insertions, 15 deletions
diff --git a/CHANGELOG b/CHANGELOG
index ee5960b15..dc74f81ce 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -1,6 +1,7 @@
CHANGELOG Roundcube Webmail
===========================
+- Fix bug where serialized strings were truncated in PDO::quote() (#1489142)
- Fix displaying messages with invalid self-closing HTML tags (#1489137)
- Fix PHP warning when responding to a message with many Return-Path headers (#1489136)
- Fix unintentional compose window resize (#1489114)
diff --git a/program/lib/Roundcube/rcube_cache.php b/program/lib/Roundcube/rcube_cache.php
index 92f12a8bf..deaba68e9 100644
--- a/program/lib/Roundcube/rcube_cache.php
+++ b/program/lib/Roundcube/rcube_cache.php
@@ -145,7 +145,7 @@ class rcube_cache
*/
function write($key, $data)
{
- return $this->write_record($key, $this->packed ? serialize($data) : $data);
+ return $this->write_record($key, $this->serialize($data));
}
@@ -219,7 +219,7 @@ class rcube_cache
if ($this->cache_changes[$key]) {
// Make sure we're not going to write unchanged data
// by comparing current md5 sum with the sum calculated on DB read
- $data = $this->packed ? serialize($data) : $data;
+ $data = $this->serialize($data);
if (!$this->cache_sums[$key] || $this->cache_sums[$key] != md5($data)) {
$this->write_record($key, $data);
@@ -255,7 +255,7 @@ class rcube_cache
if ($data) {
$md5sum = md5($data);
- $data = $this->packed ? unserialize($data) : $data;
+ $data = $this->unserialize($data);
if ($nostore) {
return $data;
@@ -283,7 +283,7 @@ class rcube_cache
$key = substr($sql_arr['cache_key'], strlen($this->prefix)+1);
$md5sum = $sql_arr['data'] ? md5($sql_arr['data']) : null;
if ($sql_arr['data']) {
- $data = $this->packed ? unserialize($sql_arr['data']) : $sql_arr['data'];
+ $data = $this->unserialize($sql_arr['data']);
}
if ($nostore) {
@@ -364,7 +364,6 @@ class rcube_cache
* @param string $key Cache key name or pattern
* @param boolean $prefix_mode Enable it to clear all keys starting
* with prefix specified in $key
- *
*/
private function remove_record($key=null, $prefix_mode=false)
{
@@ -553,4 +552,28 @@ class rcube_cache
// This way each cache will have its own index
return sprintf('%d:%s%s', $this->userid, $this->prefix, 'INDEX');
}
+
+ /**
+ * Serializes data for storing
+ */
+ private function serialize($data)
+ {
+ if ($this->type == 'db') {
+ return $this->db->encode($data, $this->packed);
+ }
+
+ return $this->packed ? serialize($data) : $data;
+ }
+
+ /**
+ * Unserializes serialized data
+ */
+ private function unserialize($data)
+ {
+ if ($this->type == 'db') {
+ return $this->db->decode($data, $this->packed);
+ }
+
+ return $this->packed ? @unserialize($data) : $data;
+ }
}
diff --git a/program/lib/Roundcube/rcube_db.php b/program/lib/Roundcube/rcube_db.php
index 2f0a32ad6..adfe3ca3c 100644
--- a/program/lib/Roundcube/rcube_db.php
+++ b/program/lib/Roundcube/rcube_db.php
@@ -789,12 +789,19 @@ class rcube_db
/**
* Encodes non-UTF-8 characters in string/array/object (recursive)
*
- * @param mixed $input Data to fix
+ * @param mixed $input Data to fix
+ * @param bool $serialized Enable serialization
*
* @return mixed Properly UTF-8 encoded data
*/
- public static function encode($input)
+ public static function encode($input, $serialized = false)
{
+ // use Base64 encoding to workaround issues with invalid
+ // or null characters in serialized string (#1489142)
+ if ($serialized) {
+ return base64_encode(serialize($input));
+ }
+
if (is_object($input)) {
foreach (get_object_vars($input) as $idx => $value) {
$input->$idx = self::encode($value);
@@ -805,6 +812,7 @@ class rcube_db
foreach ($input as $idx => $value) {
$input[$idx] = self::encode($value);
}
+
return $input;
}
@@ -814,12 +822,19 @@ class rcube_db
/**
* Decodes encoded UTF-8 string/object/array (recursive)
*
- * @param mixed $input Input data
+ * @param mixed $input Input data
+ * @param bool $serialized Enable serialization
*
* @return mixed Decoded data
*/
- public static function decode($input)
+ public static function decode($input, $serialized = false)
{
+ if ($serialized) {
+ // use Base64 encoding to workaround issues with invalid
+ // or null characters in serialized string (#1489142)
+ return @unserialize(base64_decode($input));
+ }
+
if (is_object($input)) {
foreach (get_object_vars($input) as $idx => $value) {
$input->$idx = self::decode($value);
diff --git a/program/lib/Roundcube/rcube_imap_cache.php b/program/lib/Roundcube/rcube_imap_cache.php
index 89e3ceb6f..a3bdf2196 100644
--- a/program/lib/Roundcube/rcube_imap_cache.php
+++ b/program/lib/Roundcube/rcube_imap_cache.php
@@ -419,7 +419,7 @@ class rcube_imap_cache
}
unset($msg->flags);
- $msg = serialize($this->db->encode($msg));
+ $msg = $this->db->encode($msg, true);
// update cache record (even if it exists, the update
// here will work as select, assume row exist if affected_rows=0)
@@ -641,7 +641,7 @@ class rcube_imap_cache
if ($sql_arr = $this->db->fetch_assoc($sql_result)) {
$data = explode('@', $sql_arr['data']);
- $index = @unserialize($data[0]);
+ $index = $this->db->decode($data[0], true);
unset($data[0]);
if (empty($index)) {
@@ -678,7 +678,7 @@ class rcube_imap_cache
if ($sql_arr = $this->db->fetch_assoc($sql_result)) {
$data = explode('@', $sql_arr['data']);
- $thread = @unserialize($data[0]);
+ $thread = $this->db->decode($data[0], true);
unset($data[0]);
if (empty($thread)) {
@@ -704,7 +704,7 @@ class rcube_imap_cache
$data, $mbox_data = array(), $exists = false, $modseq = null)
{
$data = array(
- serialize($data),
+ $this->db->encode($data, true),
$sort_field,
(int) $this->skip_deleted,
(int) $mbox_data['UIDVALIDITY'],
@@ -737,7 +737,7 @@ class rcube_imap_cache
private function add_thread_row($mailbox, $data, $mbox_data = array(), $exists = false)
{
$data = array(
- serialize($data),
+ $this->db->encode($data, true),
(int) $this->skip_deleted,
(int) $mbox_data['UIDVALIDITY'],
(int) $mbox_data['UIDNEXT'],
@@ -1069,7 +1069,7 @@ class rcube_imap_cache
*/
private function build_message($sql_arr)
{
- $message = $this->db->decode(unserialize($sql_arr['data']));
+ $message = $this->db->decode($sql_arr['data'], true);
if ($message) {
$message->flags = array();