Changeset 2157

Show
Ignore:
Timestamp:
2008-07-03 11:32:33 (21 months ago)
Author:
martinkou
Message:

Fixed #2220: Email links from the Link dialog are now encoded by default to prevent being harvested by spammers.

Location:
FCKeditor/trunk
Files:
3 modified

Legend:

Unmodified
Added
Removed
  • FCKeditor/trunk/editor/dialog/fck_link/fck_link.js

    r2043 r2157  
    7878var oParser = new Object() ; 
    7979 
    80 oParser.ParseEMailUrl = function( emailUrl ) 
     80// This method simply returns the two inputs in numerical order. You can even 
     81// provide strings, as the method would parseInt() the values. 
     82oParser.SortNumerical = function(a, b) 
     83{ 
     84        return parseInt( a ) - parseInt( b ) ; 
     85} 
     86 
     87oParser.ParseEMailParams = function(sParams) 
     88{ 
     89        // Initialize the oEMailParams object. 
     90        var oEMailParams = new Object() ; 
     91        oEMailParams.Subject = '' ; 
     92        oEMailParams.Body = '' ; 
     93 
     94        var aMatch = sParams.match( /(^|^\?|&)subject=([^&]+)/i ) ; 
     95        if ( aMatch ) oEMailParams.Subject = decodeURIComponent( aMatch[2] ) ; 
     96 
     97        aMatch = sParams.match( /(^|^\?|&)body=([^&]+)/i ) ; 
     98        if ( aMatch ) oEMailParams.Body = decodeURIComponent( aMatch[2] ) ; 
     99 
     100        return oEMailParams ; 
     101} 
     102 
     103// This method returns either an object containing the email info, or FALSE 
     104// if the parameter is not an email link. 
     105oParser.ParseEMailUri = function( sUrl ) 
    81106{ 
    82107        // Initializes the EMailInfo object. 
    83108        var oEMailInfo = new Object() ; 
    84         oEMailInfo.Address      = '' ; 
    85         oEMailInfo.Subject      = '' ; 
    86         oEMailInfo.Body         = '' ; 
    87  
    88         var oParts = emailUrl.match( /^([^\?]+)\??(.+)?/ ) ; 
    89         if ( oParts ) 
    90         { 
    91                 // Set the e-mail address. 
    92                 oEMailInfo.Address = oParts[1] ; 
    93  
    94                 // Look for the optional e-mail parameters. 
    95                 if ( oParts[2] ) 
    96                 { 
    97                         var oMatch = oParts[2].match( /(^|&)subject=([^&]+)/i ) ; 
    98                         if ( oMatch ) oEMailInfo.Subject = decodeURIComponent( oMatch[2] ) ; 
    99  
    100                         oMatch = oParts[2].match( /(^|&)body=([^&]+)/i ) ; 
    101                         if ( oMatch ) oEMailInfo.Body = decodeURIComponent( oMatch[2] ) ; 
    102                 } 
    103         } 
    104  
    105         return oEMailInfo ; 
     109        oEMailInfo.Address = '' ; 
     110        oEMailInfo.Subject = '' ; 
     111        oEMailInfo.Body = '' ; 
     112 
     113        var aLinkInfo = sUrl.match( /^(\w+):(.*)$/ ) ; 
     114        if ( aLinkInfo && aLinkInfo[1] == 'mailto' ) 
     115        { 
     116                // This seems to be an unprotected email link. 
     117                var aParts = aLinkInfo[2].match( /^([^\?]+)\??(.+)?/ ) ; 
     118                if ( aParts ) 
     119                { 
     120                        // Set the e-mail address. 
     121                        oEMailInfo.Address = aParts[1] ; 
     122 
     123                        // Look for the optional e-mail parameters. 
     124                        if ( aParts[2] ) 
     125                        { 
     126                                var oEMailParams = oParser.ParseEMailParams( aParts[2] ) ; 
     127                                oEMailInfo.Subject = oEMailParams.Subject ; 
     128                                oEMailInfo.Body = oEMailParams.Body ; 
     129                        } 
     130                } 
     131                return oEMailInfo ; 
     132        } 
     133        else if ( aLinkInfo && aLinkInfo[1] == 'javascript' ) 
     134        { 
     135                // This may be a protected email. 
     136 
     137                // Try to match the url against the EMailProtectionFunction. 
     138                var func = FCKConfig.EMailProtectionFunction ; 
     139                if ( func != null ) 
     140                { 
     141                        try 
     142                        { 
     143                                // Escape special chars. 
     144                                func = func.replace( /([/^$*+.?()\[\]])/g, '\\$1' ) ; 
     145 
     146                                // Define the possible keys. 
     147                                var keys = new Array('NAME', 'DOMAIN', 'SUBJECT', 'BODY') ; 
     148 
     149                                // Get the order of the keys (hold them in the array <pos>) and 
     150                                // the function replaced by regular expression patterns. 
     151                                var sFunc = func ; 
     152                                var pos = new Array() ; 
     153                                for ( var i = 0 ; i < keys.length ; i ++ ) 
     154                                { 
     155                                        var rexp = new RegExp( keys[i] ) ; 
     156                                        var p = func.search( rexp ) ; 
     157                                        if ( p >= 0 ) 
     158                                        { 
     159                                                sFunc = sFunc.replace( rexp, '\'([^\']*)\'' ) ; 
     160                                                pos[pos.length] = p + ':' + keys[i] ; 
     161                                        } 
     162                                } 
     163 
     164                                // Sort the available keys. 
     165                                pos.sort( oParser.SortNumerical ) ; 
     166 
     167                                // Replace the excaped single quotes in the url, such they do 
     168                                // not affect the regexp afterwards. 
     169                                aLinkInfo[2] = aLinkInfo[2].replace( /\\'/g, '###SINGLE_QUOTE###' ) ; 
     170 
     171                                // Create the regexp and execute it. 
     172                                var rFunc = new RegExp( '^' + sFunc + '$' ) ; 
     173                                var aMatch = rFunc.exec( aLinkInfo[2] ) ; 
     174                                if ( aMatch ) 
     175                                { 
     176                                        var aInfo = new Array(); 
     177                                        for ( var i = 1 ; i < aMatch.length ; i ++ ) 
     178                                        { 
     179                                                var k = pos[i-1].match(/^\d+:(.+)$/) ; 
     180                                                aInfo[k[1]] = aMatch[i].replace(/###SINGLE_QUOTE###/g, '\'') ; 
     181                                        } 
     182 
     183                                        // Fill the EMailInfo object that will be returned 
     184                                        oEMailInfo.Address = aInfo['NAME'] + '@' + aInfo['DOMAIN'] ; 
     185                                        oEMailInfo.Subject = decodeURIComponent( aInfo['SUBJECT'] ) ; 
     186                                        oEMailInfo.Body = decodeURIComponent( aInfo['BODY'] ) ; 
     187 
     188                                        return oEMailInfo ; 
     189                                } 
     190                        } 
     191                        catch (e) 
     192                        { 
     193                        } 
     194                } 
     195 
     196                // Try to match the email against the encode protection. 
     197                var aMatch = aLinkInfo[2].match( /^location\.href='mailto:'\+(String\.fromCharCode\([\d,]+\))\+'(.*)'$/ ) ; 
     198                if ( aMatch ) 
     199                { 
     200                        // The link is encoded 
     201                        oEMailInfo.Address = eval( aMatch[1] ) ; 
     202                        if ( aMatch[2] ) 
     203                        { 
     204                                var oEMailParams = oParser.ParseEMailParams( aMatch[2] ) ; 
     205                                oEMailInfo.Subject = oEMailParams.Subject ; 
     206                                oEMailInfo.Body = oEMailParams.Body ; 
     207                        } 
     208                        return oEMailInfo ; 
     209                } 
     210        } 
     211        return false; 
    106212} 
    107213 
    108214oParser.CreateEMailUri = function( address, subject, body ) 
    109215{ 
    110         var sBaseUri = 'mailto:' + address ; 
    111  
    112         var sParams = '' ; 
    113  
    114         if ( subject.length > 0 ) 
    115                 sParams = '?subject=' + encodeURIComponent( subject ) ; 
    116  
    117         if ( body.length > 0 ) 
    118         { 
    119                 sParams += ( sParams.length == 0 ? '?' : '&' ) ; 
    120                 sParams += 'body=' + encodeURIComponent( body ) ; 
    121         } 
    122  
    123         return sBaseUri + sParams ; 
     216        // Switch for the EMailProtection setting. 
     217        switch ( FCKConfig.EMailProtection ) 
     218        { 
     219                case 'function' : 
     220                        var func = FCKConfig.EMailProtectionFunction ; 
     221                        if ( func == null ) 
     222                        { 
     223                                if ( FCKConfig.Debug ) 
     224                                { 
     225                                        alert('EMailProtection alert!\nNo function defined. Please set "FCKConfig.EMailProtectionFunction"') ; 
     226                                } 
     227                                return ''; 
     228                        } 
     229 
     230                        // Split the email address into name and domain parts. 
     231                        var aAddressParts = address.split( '@', 2 ) ; 
     232                        if ( aAddressParts[1] == undefined ) 
     233                        { 
     234                                aAddressParts[1] = '' ; 
     235                        } 
     236 
     237                        // Replace the keys by their values (embedded in single quotes). 
     238                        func = func.replace(/NAME/g, "'" + aAddressParts[0].replace(/'/g, '\\\'') + "'") ; 
     239                        func = func.replace(/DOMAIN/g, "'" + aAddressParts[1].replace(/'/g, '\\\'') + "'") ; 
     240                        func = func.replace(/SUBJECT/g, "'" + encodeURIComponent( subject ).replace(/'/g, '\\\'') + "'") ; 
     241                        func = func.replace(/BODY/g, "'" + encodeURIComponent( body ).replace(/'/g, '\\\'') + "'") ; 
     242                        return 'javascript:' + func ; 
     243                        break ; 
     244                case 'encode' : 
     245                        var aParams = [] ; 
     246                        var aAddressCode = [] ; 
     247 
     248                        if ( subject.length > 0 ) 
     249                                aParams.push( 'subject='+ encodeURIComponent( subject ) ) ; 
     250                        if ( body.length > 0 ) 
     251                                aParams.push( 'body=' + encodeURIComponent( body ) ) ; 
     252                        for ( var i = 0 ; i < address.length ; i++ ) 
     253                                aAddressCode.push( address.charCodeAt( i ) ) ; 
     254 
     255                        return 'javascript:location.href=\'mailto:\'+String.fromCharCode(' + aAddressCode.join( ',' ) + ')+\'?' + aParams.join( '&' ) + '\'' ; 
     256                default : // 'none' 
     257                        var sBaseUri = 'mailto:' + address ; 
     258 
     259                        var sParams = '' ; 
     260 
     261                        if ( subject.length > 0 ) 
     262                                sParams = '?subject=' + encodeURIComponent( subject ) ; 
     263 
     264                        if ( body.length > 0 ) 
     265                        { 
     266                                sParams += ( sParams.length == 0 ? '?' : '&' ) ; 
     267                                sParams += 'body=' + encodeURIComponent( body ) ; 
     268                        } 
     269 
     270                        return sBaseUri + sParams ; 
     271        } 
    124272} 
    125273 
     
    264412        var sProtocol = oRegex.UriProtocol.exec( sHRef ) ; 
    265413 
    266         if ( sProtocol ) 
     414        // Search for a protected email link. 
     415        var oEMailInfo = oParser.ParseEMailUri( sHRef ); 
     416 
     417        if ( oEMailInfo ) 
     418        { 
     419                sType = 'email' ; 
     420 
     421                GetE('txtEMailAddress').value = oEMailInfo.Address ; 
     422                GetE('txtEMailSubject').value = oEMailInfo.Subject ; 
     423                GetE('txtEMailBody').value    = oEMailInfo.Body ; 
     424        } 
     425        else if ( sProtocol ) 
    267426        { 
    268427                sProtocol = sProtocol[0].toLowerCase() ; 
     
    271430                // Remove the protocol and get the remaining URL. 
    272431                var sUrl = sHRef.replace( oRegex.UriProtocol, '' ) ; 
    273  
    274                 if ( sProtocol == 'mailto:' )   // It is an e-mail link. 
    275                 { 
    276                         sType = 'email' ; 
    277  
    278                         var oEMailInfo = oParser.ParseEMailUrl( sUrl ) ; 
    279                         GetE('txtEMailAddress').value   = oEMailInfo.Address ; 
    280                         GetE('txtEMailSubject').value   = oEMailInfo.Subject ; 
    281                         GetE('txtEMailBody').value              = oEMailInfo.Body ; 
    282                 } 
    283                 else                            // It is a normal link. 
    284                 { 
    285                         sType = 'url' ; 
    286                         GetE('txtUrl').value = sUrl ; 
    287                 } 
     432                sType = 'url' ; 
     433                GetE('txtUrl').value = sUrl ; 
    288434        } 
    289435        else if ( sHRef.substr(0,1) == '#' && sHRef.length > 1 )        // It is an anchor link. 
  • FCKeditor/trunk/fckconfig.js

    r2095 r2157  
    7676FCKConfig.FormatOutput          = true ; 
    7777FCKConfig.FormatIndentator      = '    ' ; 
     78 
     79FCKConfig.EMailProtection = 'encode' ; // none | encode | function 
     80FCKConfig.EMailProtectionFunction = 'mt(NAME,DOMAIN,SUBJECT,BODY)' ; 
    7881 
    7982FCKConfig.StartupFocus  = false ; 
  • FCKeditor/trunk/_whatsnew.html

    r2145 r2157  
    4040                <li>[<a target="_blank" href="http://dev.fckeditor.net/ticket/439">#439</a>] Added a new 
    4141                        right-click menu option for opening links in the editor.</li> 
     42                <li>[<a target="_blank" href="http://dev.fckeditor.net/ticket/2220">#2220</a>] Email links 
     43                        from the Link dialog are now encoded by default to prevent being harvested by spammers. 
     44                        (Kudos to asuter for proposing the patch) </li> 
    4245        </ul> 
    4346        <p>