Changeset 5514 in subversion


Ignore:
Timestamp:
Nov 30, 2011 6:35:43 AM (19 months ago)
Author:
alec
Message:
  • Applied fixes from trunk up to r5512
Location:
branches/release-0.7
Files:
8 edited

Legend:

Unmodified
Added
Removed
  • branches/release-0.7/CHANGELOG

    r5499 r5514  
    22=========================== 
    33 
     4- Fix handling of empty <U> tags in HTML messages (#1488225) 
     5- Add content filter for embedded attachments to protect from XSS on IE (#1487895) 
    46- Use strpos() instead of strstr() when possible (#1488211) 
    57- Fix handling HTML entities when converting HTML to text (#1488212) 
  • branches/release-0.7/plugins/archive/localization/fr_FR.inc

    r2953 r5514  
    33$labels = array(); 
    44$labels['buttontitle'] = 'Archiver ce message'; 
    5 $labels['archived'] = 'Message archivé avec success'; 
     5$labels['archived'] = 'Message archivé avec success'; 
    66$labels['archivefolder'] = 'Archive'; 
    77 
  • branches/release-0.7/program/include/rcube_ldap.php

    r5491 r5514  
    733733            $function = $this->_scope2func($this->prop['scope']); 
    734734            $this->ldap_result = @$function($this->conn, $this->base_dn, $this->filter ? $this->filter : '(objectclass=*)', 
    735                 array_values($this->fieldmap), 0, (int)$this->prop['sizelimit'], (int)$this->prop['timelimit']); 
     735                array_values($this->fieldmap), 0, $this->page_size, (int)$this->prop['timelimit']); 
    736736 
    737737            $this->result = new rcube_result_set(0); 
    738738 
    739             if (!$this->ldap_result) { 
     739            if (!$this->ldap_result) { 
    740740                $this->_debug("S: ".ldap_error($this->conn)); 
    741                 return $this->result; 
    742             } 
    743  
    744             $this->_debug("S: ".ldap_count_entries($this->conn, $this->ldap_result)." record(s)"); 
     741                return $this->result; 
     742            } 
     743 
     744            $this->_debug("S: ".ldap_count_entries($this->conn, $this->ldap_result)." record(s)"); 
    745745 
    746746            // get all entries of this page and post-filter those that really match the query 
     
    10441044        $deletedata = array(); 
    10451045 
    1046         // flatten composite fields in $record 
    1047         if (is_array($record['address'])) { 
    1048           foreach ($record['address'] as $i => $struct) { 
    1049             foreach ($struct as $col => $val) { 
    1050               $record[$col][$i] = $val; 
    1051             } 
    1052           } 
    1053         } 
     1046        $ldap_data = $this->_map_data($save_cols); 
     1047        $old_data = $record['_raw_attrib']; 
    10541048 
    10551049        foreach ($this->fieldmap as $col => $fld) { 
    1056             $val = $save_cols[$col]; 
     1050            $val = $ldap_data[$fld]; 
    10571051            if ($fld) { 
    10581052                // remove empty array values 
     
    10601054                    $val = array_filter($val); 
    10611055                // The field does exist compare it to the ldap record. 
    1062                 if ($record[$col] != $val) { 
     1056                if ($old_data[$fld] != $val) { 
    10631057                    // Changed, but find out how. 
    1064                     if (!isset($record[$col])) { 
     1058                    if (!isset($old_data[$fld])) { 
    10651059                        // Field was not set prior, need to add it. 
    10661060                        $newdata[$fld] = $val; 
    1067                     } // end if 
    1068                     elseif ($val == '') { 
     1061                    } 
     1062                    else if ($val == '') { 
    10691063                        // Field supplied is empty, verify that it is not required. 
    10701064                        if (!in_array($fld, $this->prop['required_fields'])) { 
    10711065                            // It is not, safe to clear. 
    1072                             $deletedata[$fld] = $record[$col]; 
    1073                         } // end if 
     1066                            $deletedata[$fld] = $old_data[$fld]; 
     1067                        } 
    10741068                    } // end elseif 
    10751069                    else { 
    10761070                        // The data was modified, save it out. 
    10771071                        $replacedata[$fld] = $val; 
    1078                     } // end else 
     1072                    } 
    10791073                } // end if 
    10801074            } // end if 
     
    13041298                if (!($value = $rec[$lf][$i])) 
    13051299                    continue; 
     1300 
     1301                $out['_raw_attrib'][$lf][$i] = $value; 
     1302 
    13061303                if ($rf == 'email' && $this->mail_domain && !strpos($value, '@')) 
    13071304                    $out[$rf][] = sprintf('%s@%s', $value, $this->mail_domain); 
     
    13161313            // Make sure name fields aren't arrays (#1488108) 
    13171314            if (is_array($out[$rf]) && in_array($rf, array('name', 'surname', 'firstname', 'middlename', 'nickname'))) { 
    1318                 $out[$rf] = $out[$rf][0]; 
     1315                $out[$rf] = $out['_raw_attrib'][$lf] = $out[$rf][0]; 
    13191316            } 
    13201317        } 
     
    13381335    private function _map_data($save_cols) 
    13391336    { 
     1337        // flatten composite fields first 
     1338        foreach ($this->coltypes as $col => $colprop) { 
     1339            if (is_array($colprop['childs']) && ($values = $this->get_col_values($col, $save_cols, false))) { 
     1340                foreach ($values as $subtype => $childs) { 
     1341                    $subtype = $subtype ? ':'.$subtype : ''; 
     1342                    foreach ($childs as $i => $child_values) { 
     1343                        foreach ((array)$child_values as $childcol => $value) { 
     1344                            $save_cols[$childcol.$subtype][$i] = $value; 
     1345                        } 
     1346                    } 
     1347                } 
     1348            } 
     1349        } 
     1350 
    13401351        $ldap_data = array(); 
    13411352        foreach ($this->fieldmap as $col => $fld) { 
     
    15871598        $new_dn = "cn=$group_name,$base_dn"; 
    15881599        $new_gid = self::dn_encode($group_name); 
     1600        $member_attr = $this->prop['groups']['member_attr']; 
    15891601        $name_attr = $this->prop['groups']['name_attr']; 
    15901602 
     
    15921604            'objectClass' => $this->prop['groups']['object_classes'], 
    15931605            $name_attr => $group_name, 
     1606            $member_attr => '', 
    15941607        ); 
    15951608 
  • branches/release-0.7/program/include/rcube_message.php

    r5374 r5514  
    143143     * @return string URL or false if part does not exist 
    144144     */ 
    145     public function get_part_url($mime_id) 
     145    public function get_part_url($mime_id, $embed = false) 
    146146    { 
    147147        if ($this->mime_parts[$mime_id]) 
    148             return $this->opt['get_url'] . '&_part=' . $mime_id; 
     148            return $this->opt['get_url'] . '&_part=' . $mime_id . ($embed ? '&_embed=1' : ''); 
    149149        else 
    150150            return false; 
     
    512512 
    513513                foreach ($this->inline_parts as $inline_object) { 
    514                     $part_url = $this->get_part_url($inline_object->mime_id); 
     514                    $part_url = $this->get_part_url($inline_object->mime_id, true); 
    515515                    if ($inline_object->content_id) 
    516516                        $a_replaces['cid:'.$inline_object->content_id] = $part_url; 
  • branches/release-0.7/program/lib/washtml.php

    r5434 r5514  
    109109  /* Block elements which could be empty but cannot be returned in short form (<tag />) */ 
    110110  static $block_elements = array('div', 'p', 'pre', 'blockquote', 'a', 'font', 'center', 
    111     'table', 'ul', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'ol', 'dl', 'strong', 'i', 'b'); 
     111    'table', 'ul', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'ol', 'dl', 'strong', 'i', 'b', 'u'); 
    112112 
    113113  /* State for linked objects in HTML */ 
  • branches/release-0.7/program/steps/mail/func.inc

    r5415 r5514  
    551551 * @return string Clean HTML 
    552552 */ 
    553 function rcmail_wash_html($html, $p = array(), $cid_replaces) 
     553function rcmail_wash_html($html, $p, $cid_replaces) 
    554554{ 
    555555  global $REMOTE_OBJECTS; 
     
    10531053        $out .= html::tag('hr') . html::p(array('align' => "center"), 
    10541054          html::img(array( 
    1055             'src' => $MESSAGE->get_part_url($attach_prop->mime_id), 
     1055            'src' => $MESSAGE->get_part_url($attach_prop->mime_id, true), 
    10561056            'title' => $attach_prop->filename, 
    10571057            'alt' => $attach_prop->filename, 
  • branches/release-0.7/program/steps/mail/get.inc

    r5481 r5514  
    135135      header("Content-Disposition: $disposition; filename=\"$filename\""); 
    136136 
    137       // turn off output buffering and print part content 
    138       if ($part->body) 
    139         echo $part->body; 
    140       else if ($part->size) 
    141         $IMAP->get_message_part($MESSAGE->uid, $part->mime_id, $part, true); 
     137      // do content filtering to avoid XSS through fake images 
     138      if (!empty($_REQUEST['_embed']) && $browser->ie && $browser->ver <= 8) { 
     139        if ($part->body) 
     140          echo preg_match('/<(script|iframe|object)/i', $part->body) ? '' : $part->body; 
     141        else if ($part->size) { 
     142          $stdout = fopen('php://output', 'w'); 
     143          stream_filter_register('rcube_content', 'rcube_content_filter') or die('Failed to register content filter'); 
     144          stream_filter_append($stdout, 'rcube_content'); 
     145          $IMAP->get_message_part($MESSAGE->uid, $part->mime_id, $part, false, $stdout); 
     146        } 
     147      } 
     148      else { 
     149        // turn off output buffering and print part content 
     150        if ($part->body) 
     151          echo $part->body; 
     152        else if ($part->size) 
     153          $IMAP->get_message_part($MESSAGE->uid, $part->mime_id, $part, true); 
     154      } 
    142155    } 
    143156 
     
    167180 
    168181 
     182 
     183/** 
     184 * PHP stream filter to detect html/javascript code in attachments 
     185 */ 
     186class rcube_content_filter extends php_user_filter 
     187{ 
     188  private $buffer = ''; 
     189  private $cutoff = 2048; 
     190 
     191  function onCreate() 
     192  { 
     193    $this->cutoff = rand(2048, 3027); 
     194    return true; 
     195  } 
     196 
     197  function filter($in, $out, &$consumed, $closing) 
     198  { 
     199    while ($bucket = stream_bucket_make_writeable($in)) { 
     200      $this->buffer .= $bucket->data; 
     201 
     202      // check for evil content and abort 
     203      if (preg_match('/<(script|iframe|object)/i', $this->buffer)) 
     204        return PSFS_ERR_FATAL; 
     205 
     206      // keep buffer small enough 
     207      if (strlen($this->buffer) > 4096) 
     208        $this->buffer = substr($this->buffer, $this->cutoff); 
     209 
     210      $consumed += $bucket->datalen; 
     211      stream_bucket_append($out, $bucket); 
     212    } 
     213 
     214    return PSFS_PASS_ON; 
     215  } 
     216} 
     217 
  • branches/release-0.7/program/steps/mail/show.inc

    r5415 r5514  
    133133        $ol .= html::tag('li', null, 
    134134          html::a(array( 
    135             'href' => $MESSAGE->get_part_url($attach_prop->mime_id), 
     135            'href' => $MESSAGE->get_part_url($attach_prop->mime_id, false), 
    136136            'onclick' => sprintf( 
    137137              'return %s.command(\'load-attachment\',{part:\'%s\', mimetype:\'%s\'},this)', 
Note: See TracChangeset for help on using the changeset viewer.