Aleksander Machniak
2013-06-02 72c8504b99fbd423651bab0180a044c489ca05cc
Fix bug where serialized strings were truncated in PDO::quote() (#1489142)

Conflicts:

CHANGELOG
program/lib/Roundcube/rcube_cache_shared.php
4 files modified
69 ■■■■ changed files
CHANGELOG 1 ●●●● patch | view | raw | blame | history
program/lib/Roundcube/rcube_cache.php 33 ●●●● patch | view | raw | blame | history
program/lib/Roundcube/rcube_db.php 23 ●●●● patch | view | raw | blame | history
program/lib/Roundcube/rcube_imap_cache.php 12 ●●●● patch | view | raw | blame | history
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)
program/lib/Roundcube/rcube_cache.php
@@ -145,7 +145,7 @@
     */
    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 @@
            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 @@
            if ($data) {
                $md5sum = md5($data);
                $data   = $this->packed ? unserialize($data) : $data;
                $data   = $this->unserialize($data);
                if ($nostore) {
                    return $data;
@@ -283,7 +283,7 @@
                $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 @@
     * @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 @@
        // 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;
    }
}
program/lib/Roundcube/rcube_db.php
@@ -789,12 +789,19 @@
    /**
     * 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 @@
            foreach ($input as $idx => $value) {
                $input[$idx] = self::encode($value);
            }
            return $input;
        }
@@ -814,12 +822,19 @@
    /**
     * 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);
program/lib/Roundcube/rcube_imap_cache.php
@@ -419,7 +419,7 @@
        }
        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 @@
        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 @@
        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 @@
        $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 @@
    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 @@
     */
    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();