~ubuntu-branches/ubuntu/karmic/squirrelmail/karmic

« back to all changes in this revision

Viewing changes to functions/mime.php

  • Committer: Bazaar Package Importer
  • Author(s): Thijs Kinkhorst
  • Date: 2006-12-04 09:18:09 UTC
  • mfrom: (1.1.6 upstream)
  • Revision ID: james.westby@ubuntu.com-20061204091809-f5tmhfdfy71y0cwn
Tags: 2:1.4.9a-1
* New upstream security release.
  - Additionally tightens HTML filter for IE <= 5 parsing
    absolutely everything and it's horse.

Show diffs side-by-side

added added

removed removed

Lines of Context:
8
8
 *
9
9
 * @copyright &copy; 1999-2006 The SquirrelMail Project Team
10
10
 * @license http://opensource.org/licenses/gpl-license.php GNU Public License
11
 
 * @version $Id: mime.php,v 1.265.2.68 2006/06/20 06:14:53 jervfors Exp $
 
11
 * @version $Id: mime.php,v 1.265.2.71 2006/12/03 23:06:45 stekkel Exp $
12
12
 * @package squirrelmail
13
13
 */
14
14
 
477
477
        if ($where && $what) {
478
478
           $defaultlink .= '&amp;where='. urlencode($where).'&amp;what='.urlencode($what);
479
479
        }
480
 
 
 
480
        // IE does make use of mime content sniffing. Forcing a download
 
481
        // prohibit execution of XSS inside an application/octet-stream attachment
 
482
        if ($type0 == 'application' && $type1 == 'octet-stream') {
 
483
            $defaultlink .= '&amp;absolute_dl=true';
 
484
        }
481
485
        /* This executes the attachment hook with a specific MIME-type.
482
486
         * If that doesn't have results, it tries if there's a rule
483
 
         * for a more generic type.
 
487
         * for a more generic type. Finally, a hook for ALL attachment
 
488
         * types is run as well.
484
489
         */
485
490
        $hookresults = do_hook("attachment $type0/$type1", $links,
486
491
                $startMessage, $id, $urlMailbox, $ent, $defaultlink,
490
495
                    $startMessage, $id, $urlMailbox, $ent, $defaultlink,
491
496
                    $display_filename, $where, $what);
492
497
        }
 
498
        $hookresults = do_hook("attachment */*", $hookresults[1],
 
499
                $startMessage, $id, $urlMailbox, $ent, $hookresults[6],
 
500
                $display_filename, $where, $what);
493
501
 
494
502
        $links = $hookresults[1];
495
503
        $defaultlink = $hookresults[6];
851
859
/**
852
860
 * Encodes string according to rfc2047 B encoding header formating rules
853
861
 *
854
 
 * It is recommended way to encode headers with character sets that store 
 
862
 * It is recommended way to encode headers with character sets that store
855
863
 * symbols in more than one byte.
856
864
 *
857
865
 * Function requires mbstring support. If required mbstring functions are missing,
858
866
 * function returns false and sets E_USER_WARNING level error message.
859
867
 *
860
 
 * Minimal requirements - php 4.0.6 with mbstring extension. Please note, 
861
 
 * that mbstring functions will generate E_WARNING errors, if unsupported 
 
868
 * Minimal requirements - php 4.0.6 with mbstring extension. Please note,
 
869
 * that mbstring functions will generate E_WARNING errors, if unsupported
862
870
 * character set is used. mb_encode_mimeheader function provided by php
863
871
 * mbstring extension is not used in order to get better control of header
864
872
 * encoding.
865
873
 *
866
 
 * Used php code functions - function_exists(), trigger_error(), strlen() 
867
 
 * (is used with charset names and base64 strings). Used php mbstring 
 
874
 * Used php code functions - function_exists(), trigger_error(), strlen()
 
875
 * (is used with charset names and base64 strings). Used php mbstring
868
876
 * functions - mb_strlen and mb_substr.
869
877
 *
870
 
 * Related documents: rfc 2045 (BASE64 encoding), rfc 2047 (mime header 
 
878
 * Related documents: rfc 2045 (BASE64 encoding), rfc 2047 (mime header
871
879
 * encoding), rfc 2822 (header folding)
872
880
 *
873
881
 * @param string $string header string that must be encoded
874
 
 * @param string $charset character set. Must be supported by mbstring extension. 
 
882
 * @param string $charset character set. Must be supported by mbstring extension.
875
883
 * Use sq_mb_list_encodings() to detect supported charsets.
876
884
 * @return string string encoded according to rfc2047 B encoding formating rules
877
885
 * @since 1.5.1 and 1.4.6
1019
1027
}
1020
1028
 
1021
1029
/**
 
1030
 * Translate all dangerous Unicode or Shift_JIS characters which are acepted by
 
1031
 * IE as regular characters.
 
1032
 *
 
1033
 * @param  attvalue  The attribute value before dangerous characters are translated.
 
1034
 * @return attvalue  Nothing, modifies a reference value.
 
1035
 * @author Marc Groot Koerkamp.
 
1036
 */
 
1037
function sq_fixIE_idiocy(&$attvalue) {
 
1038
    // remove NUL
 
1039
    $attvalue = str_replace("\0", "", $attvalue);
 
1040
    // remove comments
 
1041
    $attvalue = preg_replace("/(\/\*.*?\*\/)/","",$attvalue);
 
1042
 
 
1043
    // IE has the evil habit of excepting every possible value for the attribute expression
 
1044
    // The table below contain characters which are valid in IE if they are used in the "expression"
 
1045
    // attribute value.
 
1046
    $aDangerousCharsReplacementTable = array(
 
1047
                        array('&#x029F;', '&#0671;' ,/* L UNICODE IPA Extension */
 
1048
                              '&#x0280;', '&#0640;' ,/* R UNICODE IPA Extension */
 
1049
                              '&#x0274;', '&#0628;' ,/* N UNICODE IPA Extension */
 
1050
                              '&#xFF25;', '&#65317' ,/* Unicode FULLWIDTH LATIN CAPITAL LETTER E */
 
1051
                              '&#xFF45;', '&#65349' ,/* Unicode FULLWIDTH LATIN SMALL LETTER E */
 
1052
                              '&#xFF38;', '&#65336;',/* Unicode FULLWIDTH LATIN CAPITAL LETTER X */
 
1053
                              '&#xFF58;', '&#65368;',/* Unicode FULLWIDTH LATIN SMALL LETTER X */
 
1054
                              '&#xFF30;', '&#65328;',/* Unicode FULLWIDTH LATIN CAPITAL LETTER P */
 
1055
                              '&#xFF50;', '&#65360;',/* Unicode FULLWIDTH LATIN SMALL LETTER P */
 
1056
                              '&#xFF32;', '&#65330;',/* Unicode FULLWIDTH LATIN CAPITAL LETTER R */
 
1057
                              '&#xFF52;', '&#65362;',/* Unicode FULLWIDTH LATIN SMALL LETTER R */
 
1058
                              '&#xFF33;', '&#65331;',/* Unicode FULLWIDTH LATIN CAPITAL LETTER S */
 
1059
                              '&#xFF53;', '&#65363;',/* Unicode FULLWIDTH LATIN SMALL LETTER S */
 
1060
                              '&#xFF29;', '&#65321;',/* Unicode FULLWIDTH LATIN CAPITAL LETTER I */
 
1061
                              '&#xFF49;', '&#65353;',/* Unicode FULLWIDTH LATIN SMALL LETTER I */
 
1062
                              '&#xFF2F;', '&#65327;',/* Unicode FULLWIDTH LATIN CAPITAL LETTER O */
 
1063
                              '&#xFF4F;', '&#65359;',/* Unicode FULLWIDTH LATIN SMALL LETTER O */
 
1064
                              '&#xFF2E;', '&#65326;',/* Unicode FULLWIDTH LATIN CAPITAL LETTER N */
 
1065
                              '&#xFF4E;', '&#65358;',/* Unicode FULLWIDTH LATIN SMALL LETTER N */
 
1066
                              '&#xFF2C;', '&#65324;',/* Unicode FULLWIDTH LATIN CAPITAL LETTER L */
 
1067
                              '&#xFF4C;', '&#65356;',/* Unicode FULLWIDTH LATIN SMALL LETTER L */
 
1068
                              '&#xFF35;', '&#65333;',/* Unicode FULLWIDTH LATIN CAPITAL LETTER U */
 
1069
                              '&#xFF55;', '&#65365;',/* Unicode FULLWIDTH LATIN SMALL LETTER U */
 
1070
                              '&#x207F;', '&#8319;' ,/* Unicode SUPERSCRIPT LATIN SMALL LETTER N */
 
1071
                              '&#x8264;', /* Shift JIS FULLWIDTH LATIN CAPITAL LETTER E */   // in unicode this is some chinese char range
 
1072
                              '&#x8285;', /* Shift JIS FULLWIDTH LATIN SMALL LETTER E */
 
1073
                              '&#x8277;', /* Shift JIS FULLWIDTH LATIN CAPITAL LETTER X */
 
1074
                              '&#x8298;', /* Shift JIS FULLWIDTH LATIN SMALL LETTER X */
 
1075
                              '&#x826F;', /* Shift JIS FULLWIDTH LATIN CAPITAL LETTER P */
 
1076
                              '&#x8290;', /* Shift JIS FULLWIDTH LATIN SMALL LETTER P */
 
1077
                              '&#x8271;', /* Shift JIS FULLWIDTH LATIN CAPITAL LETTER R */
 
1078
                              '&#x8292;', /* Shift JIS FULLWIDTH LATIN SMALL LETTER R */
 
1079
                              '&#x8272;', /* Shift JIS FULLWIDTH LATIN CAPITAL LETTER S */
 
1080
                              '&#x8293;', /* Shift JIS FULLWIDTH LATIN SMALL LETTER S */
 
1081
                              '&#x8268;', /* Shift JIS FULLWIDTH LATIN CAPITAL LETTER I */
 
1082
                              '&#x8289;', /* Shift JIS FULLWIDTH LATIN SMALL LETTER I */
 
1083
                              '&#x826E;', /* Shift JIS FULLWIDTH LATIN CAPITAL LETTER O */
 
1084
                              '&#x828F;', /* Shift JIS FULLWIDTH LATIN SMALL LETTER O */
 
1085
                              '&#x826D;', /* Shift JIS FULLWIDTH LATIN CAPITAL LETTER N */
 
1086
                              '&#x828E;'), /* Shift JIS FULLWIDTH LATIN SMALL LETTER N */
 
1087
                       array('l', 'l', 'r','r','n','n',
 
1088
                             'E','E','e','e','X','X','x','x','P','P','p','p','S','S','s','s','I','I',
 
1089
                             'i','i','O','O','o','o','N','N','n','n','L','L','l','l','U','U','u','u','n',
 
1090
                             'E','e','X','x','P','p','S','s','I','i','O','o','N','n'));
 
1091
    $attvalue = str_replace($aDangerousCharsReplacementTable[0],$aDangerousCharsReplacementTable[1],$attvalue);
 
1092
 
 
1093
    // Escapes are usefull for special characters like "{}[]()'&. In other cases they are
 
1094
    // used for XSS
 
1095
    $attvalue = preg_replace("/(\\\\)([a-zA-Z]{1})/",'$2',$attvalue);
 
1096
}
 
1097
 
 
1098
/**
1022
1099
 * This function returns the final tag out of the tag name, an array
1023
1100
 * of attributes, and the type of the tag. This function is called by
1024
1101
 * sq_sanitize internally.
1484
1561
                }
1485
1562
            }
1486
1563
        }
 
1564
 
 
1565
        /**
 
1566
         * Workaround for IE quirks
 
1567
         */
 
1568
        sq_fixIE_idiocy($attvalue);
 
1569
 
1487
1570
        /**
1488
1571
         * Remove any backslashes, entities, and extraneous whitespace.
1489
1572
         */
 
1573
        $oldattvalue = $attvalue;
1490
1574
        sq_defang($attvalue);
 
1575
        if ($attname == 'style' && $attvalue !== $oldattvalue) {
 
1576
            // entities are used in the attribute value. In 99% of the cases it's there as XSS
 
1577
            // i.e.<div style="{ left:exp&#x0280;essio&#x0274;( alert('XSS') ) }">
 
1578
            $attvalue = "idiocy";
 
1579
            $attary{$attname} = $attvalue;
 
1580
        }
1491
1581
        sq_unspace($attvalue);
1492
1582
 
1493
1583
        /**
1567
1657
function sq_fixstyle($body, $pos, $message, $id, $mailbox){
1568
1658
    global $view_unsafe_images;
1569
1659
    $me = 'sq_fixstyle';
1570
 
    $ret = sq_findnxreg($body, $pos, '</\s*style\s*>');
1571
 
    if ($ret == FALSE){
 
1660
 
 
1661
    // workaround for </style> in between comments
 
1662
    $iCurrentPos = $pos;
 
1663
    $content = '';
 
1664
    $sToken = '';
 
1665
    $bSucces = false;
 
1666
    $bEndTag = false;
 
1667
    for ($i=$pos,$iCount=strlen($body);$i<$iCount;++$i) {
 
1668
        $char = $body{$i};
 
1669
        switch ($char) {
 
1670
            case '<':
 
1671
                $sToken .= $char;
 
1672
                break;
 
1673
            case '/':
 
1674
                 if ($sToken == '<') {
 
1675
                    $sToken .= $char;
 
1676
                    $bEndTag = true;
 
1677
                 } else {
 
1678
                    $content .= $char;
 
1679
                 }
 
1680
                 break;
 
1681
            case '>':
 
1682
                 if ($bEndTag) {
 
1683
                    $sToken .= $char;
 
1684
                    if (preg_match('/\<\/\s*style\s*\>/i',$sToken,$aMatch)) {
 
1685
                        $newpos = $i + 1;
 
1686
                        $bSucces = true;
 
1687
                        break 2;
 
1688
                    } else {
 
1689
                        $content .= $sToken;
 
1690
                    }
 
1691
                    $bEndTag = false;
 
1692
                 } else {
 
1693
                    $content .= $char;
 
1694
                 }
 
1695
                 break;
 
1696
            case '!':
 
1697
                if ($sToken == '<') {
 
1698
                    // possible comment
 
1699
                    if (isset($body{$i+2}) && substr($body,$i,3) == '!--') {
 
1700
                        $i = strpos($body,'-->',$i+3);
 
1701
                        if ($i === false) { // no end comment
 
1702
                            $i = strlen($body);
 
1703
                        }
 
1704
                        $sToken = '';
 
1705
                    }
 
1706
                } else {
 
1707
                    $content .= $char;
 
1708
                }
 
1709
                break;
 
1710
            default:
 
1711
                if ($bEndTag) {
 
1712
                    $sToken .= $char;
 
1713
                } else {
 
1714
                    $content .= $char;
 
1715
                }
 
1716
                break;
 
1717
        }
 
1718
    }
 
1719
    if ($bSucces == FALSE){
1572
1720
        return array(FALSE, strlen($body));
1573
1721
    }
1574
 
    $newpos = $ret[0] + strlen($ret[2]);
1575
 
    $content = $ret[1];
 
1722
 
1576
1723
    /**
1577
1724
     * First look for general BODY style declaration, which would be
1578
1725
     * like so:
1581
1728
     */
1582
1729
    $content = preg_replace("|body(\s*\{.*?\})|si", ".bodyclass\\1", $content);
1583
1730
    $secremoveimg = '../images/' . _("sec_remove_eng.png");
 
1731
 
 
1732
    // IE Sucks hard. We have a special function for it.
 
1733
    sq_fixIE_idiocy($content);
 
1734
 
 
1735
    // remove @import line
 
1736
    $content = preg_replace("/^\s*(@import.*)$/mi","\n<!-- @import rules forbidden -->\n",$content);
 
1737
 
1584
1738
    /**
1585
1739
     * Fix url('blah') declarations.
1586
1740
     */
1587
 
    // remove NUL
1588
 
    $content = str_replace("\0", "", $content);
1589
1741
    // translate ur\l and variations into url (IE parses that)
 
1742
    // TODO check if the sq_fixIE_idiocy function already handles this.
1590
1743
    $content = preg_replace("/(\\\\)?u(\\\\)?r(\\\\)?l(\\\\)?/i",'url', $content);
1591
1744
    // NB I insert NUL characters to keep to avoid an infinite loop. They are removed after the loop.
1592
1745
    while (preg_match("/url\s*\(\s*[\'\"]?([^:]+):(.*)?[\'\"]?\s*\)/si", $content, $matches)) {
1645
1798
     * in IE.
1646
1799
     */
1647
1800
    $match   = Array('/\/\*.*\*\//',
1648
 
                     '/expression/i',
1649
 
                     '/behaviou*r/i',
1650
 
                     '/binding/i',
1651
 
                     '/include-source/i');
1652
 
    $replace = Array('', 'idiocy', 'idiocy', 'idiocy', 'idiocy');
 
1801
                    '/expression/i',
 
1802
                    '/behaviou*r/i',
 
1803
                    '/binding/i',
 
1804
                    '/include-source/i',
 
1805
                    '/javascript/i',
 
1806
                    '/script/i');
 
1807
    $replace = Array('','idiocy', 'idiocy', 'idiocy', 'idiocy', 'idiocy', 'idiocy');
1653
1808
    $contentNew = preg_replace($match, $replace, $contentTemp);
1654
1809
    if ($contentNew !== $contentTemp) {
1655
1810
        // insecure css declarations are used. From now on we don't care
2191
2346
 
2192
2347
            // This works for most types, but doesn't work with Word files
2193
2348
            header ("Content-Type: application/download; name=\"$filename\"");
2194
 
 
 
2349
            // This is to prevent IE for MIME sniffing and auto open a file in IE
 
2350
            header ("Content-Type: application/force-download; name=\"$filename\"");
2195
2351
            // These are spares, just in case.  :-)
2196
2352
            //header("Content-Type: $type0/$type1; name=\"$filename\"");
2197
2353
            //header("Content-Type: application/x-msdownload; name=\"$filename\"");
2198
2354
            //header("Content-Type: application/octet-stream; name=\"$filename\"");
 
2355
        } else if ($isIE) {
 
2356
             // This is to prevent IE for MIME sniffing and auto open a file in IE
 
2357
             header ("Content-Type: application/force-download; name=\"$filename\"");
2199
2358
        } else {
2200
2359
            // another application/octet-stream forces download for Netscape
2201
2360
            header ("Content-Type: application/octet-stream; name=\"$filename\"");
2209
2368
 
2210
2369
}  // end fn SendDownloadHeaders
2211
2370
 
2212
 
?>
 
 
b'\\ No newline at end of file'
 
2371
?>