Skip to content
This repository has been archived by the owner on Jan 6, 2023. It is now read-only.

Dev 1.4.3.3 unicode不能识别为中文 #3218

Open
wants to merge 16 commits into
base: master
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 3 additions & 13 deletions Gruntfile.js
Original file line number Diff line number Diff line change
@@ -107,16 +107,6 @@ module.exports = function (grunt) {
dest: disDir + '<%= pkg.name %>.parse.min.js'
}
},
closurecompiler: {
dist: {
src: disDir + '<%= pkg.name %>.all.js',
dest: disDir + '<%= pkg.name %>.all.min.js'
},
parse: {
src: disDir + '<%= pkg.name %>.parse.js',
dest: disDir + '<%= pkg.name %>.parse.min.js'
}
},
copy: {
base: {
files: [
@@ -229,14 +219,14 @@ module.exports = function (grunt) {
grunt.loadNpmTasks('grunt-text-replace');
grunt.loadNpmTasks('grunt-contrib-concat');
grunt.loadNpmTasks('grunt-contrib-cssmin');
grunt.loadNpmTasks('grunt-closurecompiler');
grunt.loadNpmTasks('grunt-contrib-uglify');
grunt.loadNpmTasks('grunt-contrib-copy');
grunt.loadNpmTasks('grunt-transcoding');
grunt.loadNpmTasks('grunt-contrib-clean');

grunt.registerTask('default', 'UEditor build', function () {

var tasks = [ 'concat', 'cssmin', 'closurecompiler', 'copy:base', 'copy:' + server, 'copy:demo', 'replace:demo', 'clean' ];
var tasks = [ 'concat', 'cssmin', 'uglify', 'copy:base', 'copy:' + server, 'copy:demo', 'replace:demo', 'clean' ];

if (encode === 'gbk') {
tasks.push('replace:fileEncode');
@@ -279,4 +269,4 @@ module.exports = function (grunt) {

}

};
};
10 changes: 5 additions & 5 deletions _examples/editor_api.js
100644 → 100755
Original file line number Diff line number Diff line change
@@ -89,8 +89,9 @@
'plugins/section.js',
'plugins/simpleupload.js',
'plugins/serverparam.js',
'plugins/insertfile.js',
'ui/ui.js',
'plugins/insertfile.js',
'plugins/xssFilter.js',
'ui/ui.js',
'ui/uiutils.js',
'ui/uibase.js',
'ui/separator.js',
@@ -119,9 +120,8 @@
'adapter/editorui.js',
'adapter/editor.js',
'adapter/message.js',
'adapter/autosave.js'

],
'adapter/autosave.js'
],
baseURL = '../_src/';
for (var i=0,pi;pi = paths[i++];) {
document.write('<script type="text/javascript" src="'+ baseURL + pi +'"></script>');
20 changes: 19 additions & 1 deletion _src/core/utils.js
Original file line number Diff line number Diff line change
@@ -474,6 +474,24 @@ var utils = UE.utils = {

}) : '';
},
/**
* 将url中的html字符转义, 仅转义 ', ", <, > 四个字符
* @param { String } str 需要转义的字符串
* @param { RegExp } reg 自定义的正则
* @return { String } 转义后的字符串
*/
unhtmlForUrl:function (str, reg) {
return str ? str.replace(reg || /[<">']/g, function (a) {
return {
'<':'&lt;',
'&':'&amp;',
'"':'&quot;',
'>':'&gt;',
"'":'&#39;'
}[a]

}) : '';
},

/**
* 将str中的转义字符还原成html字符
@@ -1189,4 +1207,4 @@ utils.each(['String', 'Function', 'Array', 'Number', 'RegExp', 'Object', 'Date']
UE.utils['is' + v] = function (obj) {
return Object.prototype.toString.apply(obj) == '[object ' + v + ']';
}
});
});
28 changes: 27 additions & 1 deletion _src/plugins/image.js
Original file line number Diff line number Diff line change
@@ -195,6 +195,29 @@ UE.commands['insertimage'] = {
return;
}

function unhtmlData(imgCi) {

utils.each('width,height,border,hspace,vspace'.split(','), function (item) {

if (imgCi[item]) {
imgCi[item] = parseInt(imgCi[item], 10) || 0;
}
});

utils.each('src,_src'.split(','), function (item) {

if (imgCi[item]) {
imgCi[item] = utils.unhtmlForUrl(imgCi[item]);
}
});
utils.each('title,alt'.split(','), function (item) {

if (imgCi[item]) {
imgCi[item] = utils.unhtml(imgCi[item]);
}
});
}

if (img && /img/i.test(img.tagName) && (img.className != "edui-faked-video" || img.className.indexOf("edui-upload-video")!=-1) && !img.getAttribute("word_img")) {
var first = opt.shift();
var floatStyle = first['floatStyle'];
@@ -213,6 +236,8 @@ UE.commands['insertimage'] = {
var html = [], str = '', ci;
ci = opt[0];
if (opt.length == 1) {
unhtmlData(ci);

str = '<img src="' + ci.src + '" ' + (ci._src ? ' _src="' + ci._src + '" ' : '') +
(ci.width ? 'width="' + ci.width + '" ' : '') +
(ci.height ? ' height="' + ci.height + '" ' : '') +
@@ -229,6 +254,7 @@ UE.commands['insertimage'] = {

} else {
for (var i = 0; ci = opt[i++];) {
unhtmlData(ci);
str = '<p ' + (ci['floatStyle'] == 'center' ? 'style="text-align: center" ' : '') + '><img src="' + ci.src + '" ' +
(ci.width ? 'width="' + ci.width + '" ' : '') + (ci._src ? ' _src="' + ci._src + '" ' : '') +
(ci.height ? ' height="' + ci.height + '" ' : '') +
@@ -244,4 +270,4 @@ UE.commands['insertimage'] = {

me.fireEvent('afterinsertimage', opt)
}
};
};
10 changes: 9 additions & 1 deletion _src/plugins/video.js
Original file line number Diff line number Diff line change
@@ -17,6 +17,14 @@ UE.plugins['video'] = function (){
* @param addParagraph 是否需要添加P 标签
*/
function creatInsertStr(url,width,height,id,align,classname,type){

url = utils.unhtmlForUrl(url);
align = utils.unhtml(align);
classname = utils.unhtml(classname);

width = parseInt(width, 10) || 0;
height = parseInt(height, 10) || 0;

var str;
switch (type){
case 'image':
@@ -150,4 +158,4 @@ UE.plugins['video'] = function (){
return flag ? 1 : 0;
}
};
};
};
79 changes: 79 additions & 0 deletions _src/plugins/xssFilter.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
/**
* @file xssFilter.js
* @desc xss过滤器
* @author robbenmu
*/

UE.plugins.xssFilter = function() {

var config = UEDITOR_CONFIG;
var whitList = config.whitList;

function filter(node) {

var tagName = node.tagName;
var attrs = node.attrs;

if (!whitList.hasOwnProperty(tagName)) {
node.parentNode.removeChild(node);
return false;
}

UE.utils.each(attrs, function (val, key) {

if (whitList[tagName].indexOf(key) === -1) {
node.setAttr(key);
}
});
}

// 添加inserthtml\paste等操作用的过滤规则
if (whitList && config.xssFilterRules) {
this.options.filterRules = function () {

var result = {};

UE.utils.each(whitList, function(val, key) {
result[key] = function (node) {
return filter(node);
};
});

return result;
}();
}

var tagList = [];

UE.utils.each(whitList, function (val, key) {
tagList.push(key);
});

// 添加input过滤规则
//
if (whitList && config.inputXssFilter) {
this.addInputRule(function (root) {

root.traversal(function(node) {
if (node.type !== 'element') {
return false;
}
filter(node);
});
});
}
// 添加output过滤规则
//
if (whitList && config.outputXssFilter) {
this.addOutputRule(function (root) {

root.traversal(function(node) {
if (node.type !== 'element') {
return false;
}
filter(node);
});
});
}

};
45 changes: 45 additions & 0 deletions asp/Uploader.Class.asp
Original file line number Diff line number Diff line change
@@ -104,8 +104,53 @@ Class Uploader
DoUpload stream, filename
End Function

Private Function RegExpTest(patrn, str)
Dim regEx, Match, Matches
Set regEx = New RegExp
regEx.Pattern = patrn
regEx.IgnoreCase = False
regEx.Global = True
Set Matches = regEx.Execute(str)
For Each Match in Matches
RetStr = RetStr & Match.value &" "
RetStr = RetStr & vbCRLF
Next
RegExpTest = RetStr
End Function

Private Function IpToNumber( ip )
arr=split(ip,".")
IpToNumber=256*256*256*clng(arr(0))+256*256*clng(arr(1))+256*clng(arr(2))+clng(arr(3))
End Function

Private Function IsPrivateIp( url )
Dim ip
ip = RegExpTest("\d+\.\d+\.\d+\.\d*", url)

If ip = "" Then
If RegExpTest("([\w-]+\.)+[\w-]+", url) <> "" Then
IsPrivateIp = False:Exit Function
End If
IsPrivateIp = True:Exit Function
End If

If instr(ip,"127.")=1 Then
IsPrivateIp = true:Exit Function
End If
ABegin = IpToNumber("10.0.0.0"):AEnd = IpToNumber("10.255.255.255")
BBegin = IpToNumber("172.16.0.0"):BEnd = IpToNumber("172.31.255.255")
CBegin = IpToNumber("192.168.0.0"):CEnd = IpToNumber("192.168.255.255")
IpNum = IpToNumber(ip)
IsPrivateIp = (ABegin <= IpNum and IpNum <= AEnd) or (BBegin <= IpNum and IpNum <= BEnd) or (CBegin <= IpNum and IpNum <= CEnd)
End Function

Public Function UploadRemote( url )
Dim stream, filename

If IsPrivateIp(url) Then
rsState = "Failed":Exit Function
End If

filename = Right( url, Len(url) - InStrRev(url, "/") )

Set stream = CrawlImage( url )
9 changes: 6 additions & 3 deletions dialogs/image/image.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 5 additions & 3 deletions dialogs/video/video.js
Original file line number Diff line number Diff line change
@@ -270,6 +270,8 @@

var conUrl = convert_url(url);

conUrl = utils.unhtmlForUrl(conUrl);

$G("preview").innerHTML = '<div class="previewMsg"><span>'+lang.urlError+'</span></div>'+
'<embed class="previewVideo" type="application/x-shockwave-flash" pluginspage="http://www.macromedia.com/go/getflashplayer"' +
' src="' + conUrl + '"' +
@@ -284,8 +286,8 @@
function insertUpload(){
var videoObjs=[],
uploadDir = editor.getOpt('videoUrlPrefix'),
width = $G('upload_width').value || 420,
height = $G('upload_height').value || 280,
width = parseInt($G('upload_width').value, 10) || 420,
height = parseInt($G('upload_height').value, 10) || 280,
align = findFocus("upload_alignment","name") || 'none';
for(var key in uploadVideoList) {
var file = uploadVideoList[key];
@@ -786,4 +788,4 @@
}
};

})();
})();
Binary file not shown.
11 changes: 11 additions & 0 deletions jsp/src/com/baidu/ueditor/hunter/ImageHunter.java
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
package com.baidu.ueditor.hunter;

import java.net.HttpURLConnection;
import java.net.InetAddress;
import java.net.URL;
import java.net.UnknownHostException;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
@@ -109,6 +111,15 @@ private String getPath ( String savePath, String filename, String suffix ) {
}

private boolean validHost ( String hostname ) {
try {
InetAddress ip = InetAddress.getByName(hostname);

if (ip.isSiteLocalAddress()) {
return false;
}
} catch (UnknownHostException e) {
return false;
}

return !filters.contains( hostname );

61 changes: 61 additions & 0 deletions net/App_Code/CrawlerHandler.cs
Original file line number Diff line number Diff line change
@@ -56,6 +56,11 @@ public Crawler(string sourceUrl, HttpServerUtility server)

public Crawler Fetch()
{
if (!IsExternalIPAddress(this.SourceUrl))
{
State = "INVALID_URL";
return this;
}
var request = HttpWebRequest.Create(this.SourceUrl) as HttpWebRequest;
using (var response = request.GetResponse() as HttpWebResponse)
{
@@ -100,4 +105,60 @@ public Crawler Fetch()
return this;
}
}

private bool IsExternalIPAddress(string url)
{
var uri = new Uri(url);
switch (uri.HostNameType)
{
case UriHostNameType.Dns:
var ipHostEntry = Dns.GetHostEntry(uri.DnsSafeHost);
foreach (IPAddress ipAddress in ipHostEntry.AddressList)
{
byte[] ipBytes = ipAddress.GetAddressBytes();
if (ipAddress.AddressFamily == System.Net.Sockets.AddressFamily.InterNetwork)
{
if (!IsPrivateIP(ipAddress))
{
return true;
}
}
}
break;

case UriHostNameType.IPv4:
return !IsPrivateIP(IPAddress.Parse(uri.DnsSafeHost));
}
return false;
}

private bool IsPrivateIP(IPAddress myIPAddress)
{
if (IPAddress.IsLoopback(myIPAddress)) return true;
if (myIPAddress.AddressFamily == System.Net.Sockets.AddressFamily.InterNetwork)
{
byte[] ipBytes = myIPAddress.GetAddressBytes();
// 10.0.0.0/24
if (ipBytes[0] == 10)
{
return true;
}
// 172.16.0.0/16
else if (ipBytes[0] == 172 && ipBytes[1] == 16)
{
return true;
}
// 192.168.0.0/16
else if (ipBytes[0] == 192 && ipBytes[1] == 168)
{
return true;
}
// 169.254.0.0/16
else if (ipBytes[0] == 169 && ipBytes[1] == 254)
{
return true;
}
}
return false;
}
}
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -24,7 +24,7 @@
"grunt": "~0.4.1",
"grunt-contrib-concat": "~0.3.0",
"grunt-contrib-cssmin": "~0.6.0",
"grunt-closurecompiler": "~0.9.9",
"grunt-contrib-uglify": "~1.0.1",
"grunt-contrib-copy": "~0.4.0",
"grunt-transcoding": "~0.1.1",
"grunt-text-replace": "~0.3.9",
29 changes: 26 additions & 3 deletions php/Uploader.class.php
Original file line number Diff line number Diff line change
@@ -39,7 +39,9 @@ class Uploader
"ERROR_UNKNOWN" => "未知错误",
"ERROR_DEAD_LINK" => "链接不可用",
"ERROR_HTTP_LINK" => "链接不是http链接",
"ERROR_HTTP_CONTENTTYPE" => "链接contentType不正确"
"ERROR_HTTP_CONTENTTYPE" => "链接contentType不正确",
"INVALID_URL" => "非法 URL",
"INVALID_IP" => "非法 IP"
);

/**
@@ -178,15 +180,36 @@ private function saveRemote()
$this->stateInfo = $this->getStateInfo("ERROR_HTTP_LINK");
return;
}

preg_match('/(^https*:\/\/[^:\/]+)/', $imgUrl, $matches);
$host_with_protocol = count($matches) > 1 ? $matches[1] : '';

// 判断是否是合法 url
if (!filter_var($host_with_protocol, FILTER_VALIDATE_URL)) {
$this->stateInfo = $this->getStateInfo("INVALID_URL");
return;
}

preg_match('/^https*:\/\/(.+)/', $host_with_protocol, $matches);
$host_without_protocol = count($matches) > 1 ? $matches[1] : '';

// 此时提取出来的可能是 ip 也有可能是域名,先获取 ip
$ip = gethostbyname($host_without_protocol);
// 判断是否是私有 ip
if(!filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_NO_PRIV_RANGE)) {
$this->stateInfo = $this->getStateInfo("INVALID_IP");
return;
}

//获取请求头并检测死链
$heads = get_headers($imgUrl);
$heads = get_headers($imgUrl, 1);
if (!(stristr($heads[0], "200") && stristr($heads[0], "OK"))) {
$this->stateInfo = $this->getStateInfo("ERROR_DEAD_LINK");
return;
}
//格式验证(扩展名验证和Content-Type验证)
$fileType = strtolower(strrchr($imgUrl, '.'));
if (!in_array($fileType, $this->config['allowFiles']) || stristr($heads['Content-Type'], "image")) {
if (!in_array($fileType, $this->config['allowFiles']) || !isset($heads['Content-Type']) || !stristr($heads['Content-Type'], "image")) {
$this->stateInfo = $this->getStateInfo("ERROR_HTTP_CONTENTTYPE");
return;
}
Binary file modified third-party/video-js/video-js.swf
100644 → 100755
Binary file not shown.
1 change: 1 addition & 0 deletions third-party/xss.min.js

Large diffs are not rendered by default.

910 changes: 497 additions & 413 deletions ueditor.config.js
100644 → 100755

Large diffs are not rendered by default.