CKFinder3.5.1免费和整合springboot等相关bug修复
前言
仅供学习交流。
项目本身bug修复
■ 流异常
报错:com.cksource.ckfinder.exception.AccessDeniedException
现象:在Linux后台表现为大量文件未关闭,在win下表现为一旦图片进行了操作,删除就会异常。
原因:异常为拒绝访问,根据异常找了半天,这个异常没有价值。实际上是流没有关闭,又调用了删除,留下了一个不能访问的空壳,后续写入一样名字的文件无法覆盖就会报错。
修复:
① com.cksource.ckfinder.image.Image
反编译源码50行处插入
inputStream.close();
为
public Image(InputStream inputStream) {
if (inputStream == null) {
throw new NullPointerException("Image input stream cannot be null");
} else {
try {
BufferedInputStream bufferedInputStream = new BufferedInputStream(inputStream);
this.mimeType = URLConnection.guessContentTypeFromStream(bufferedInputStream);
this.bufferedImage = ImageIO.read(bufferedInputStream);
inputStream.close();
} catch (IOException var3) {
throw new CKFinderException("Couldn't create image from stream", var3);
}
if (this.bufferedImage == null) {
throw new CKFinderException("Couldn't process image stream - data in stream is not a valid image");
}
}
}
② com.cksource.ckfinder.cache.BackendCache
反编译源码53行处修改
public void set(String key, InputStream in) {
this.backend.writeFile(this.buildPath(key), in);
try {
if (in != null) {
in.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
还有bug的话基本上都是流的问题,无脑关就对了,然后将重新编译后的class替换jar里的内容,保持项目的干净。
■ 整合springboot相关bug
报错:Consider defining a bean of type 'com.cksource.ckfinder.config.Config' in your configuration.
现象:idea里可运行,打成jar包后,启动报错。
原因:找不到配置文件,官方demo的读取配置文件方式有误。
修复:
ckfinder.yml移到resource下。
然后文件读取改为读取流。
example.ckfinder.config.CustomConfigLoader
public Config loadConfig() throws Exception {
ObjectMapper mapper = new ObjectMapper(new YAMLFactory());
return mapper.readValue(CustomConfigLoader.class.getResourceAsStream("/ckfinder.yml"), CustomConfig.class);
}
免费过程
看下官网,打扰了,一年254美刀,且依赖于父项目也就是说需要708美刀,国外的知识付费真高,足够增购一台云服务器。
ckfinder3-3.5.1\static\ckfinder\ckfinder.js,找到这个文件。
■ 代码可读化
① 初步整理
找一个格式化js的工具,将长长的一行美化,就会发现S()方法出镜率很高,统计一下
没错了,就是它。
搜索
function S(
就会看到这个方法
function S(e) {
for (var t = "", n = e.charCodeAt(0), i = 1; i < e.length; ++i) t += String.fromCharCode(e.charCodeAt(i) ^ i + n & 127);
return t
}
网上有个逆向算法,得出了加密算法,不过没有意义,因为加密结果随机。所以根据提示加密,再从文件中查找告吹。
② 大致过滤
既然无法逆向,那么只能顺着它的方法通篇调用一遍,实在太多了,没法手动调用,遍写个正则捞出来。
1、捞一份原文放入a.txt、一份带分隔符的原文。
一段丑陋的代码,cv拼拼接接没有好好写。
S(’’)或者S("")里存在斜杆实在烦,意味着引号双引号括号都有可能属于参数中的一员,导致正则很难编写,水平有限,又不想花时间研究,只能大概搞搞,过滤出大致的内容。
@Test
public void test(){
// js内容
File file = new File("...\\ck.txt");
BufferedReader reader = null;
StringBuffer sbf = new StringBuffer();
try {
reader = new BufferedReader(new FileReader(file));
String tempStr;
while ((tempStr = reader.readLine()) != null) {
sbf.append(tempStr);
}
reader.close();
sbf = new StringBuffer(sbf.toString().replace("\\\\\\\"","[dyinghao1]"));
sbf = new StringBuffer(sbf.toString().replace("\\\\\\\'","[dyinghao2]"));
sbf = new StringBuffer(sbf.toString().replace("\\\\\"","[unchange1]"));
sbf = new StringBuffer(sbf.toString().replace("\\\\\'","[unchange2]"));
sbf = new StringBuffer(sbf.toString().replace("\\\"","[gyinghao1]"));
sbf = new StringBuffer(sbf.toString().replace("\\\'","[gyinghao2]"));
sbf = new StringBuffer(sbf.toString().replace("[unchange1]","\\\\\""));
sbf = new StringBuffer(sbf.toString().replace("[unchange2]","\\\\\'"));
String tableComment = "S\\(\"[^\"]+\"\\)|S\\('[^']+'\\)" ;
Pattern pattern = Pattern.compile(tableComment) ;
Matcher matcher = pattern.matcher(sbf.toString());
while(matcher.find()) {
int count = matcher.groupCount();
for (int i = 0; i <= count; i++) {
String ret = matcher.group(i);
ret = ret
.replace("[dyinghao1]","\\\\\\\"")
.replace("[dyinghao2]","\\\\\\\'")
.replace("[gyinghao1]","\\\"")
.replace("[gyinghao2]","\\\'");
System.err.println(ret);
//System.err.println(ret +"+'@@@@@\\n'+");
}
}
} catch (IOException e) {
e.printStackTrace();
} finally {
if (reader != null) {
try {
reader.close();
} catch (IOException e1) {
e1.printStackTrace();
}
}
}
}
③ 大致翻译
过滤完了,就是翻译,由于翻译出来的内容存在换行,用带分隔符的那一份,便于分割。
选取一份ckfinder.js文件作修改
var CKFinder = function() {
console.log(②中带分隔符的字符串粘贴过来)
function __internalInit(e) {
。。。
通过浏览器打开js文件,再打开控制台输入——
var script = document.createElement('script');
script.src = "file:///E:/code/.../ckfinder.js";
document.getElementsByTagName('head')[0].appendChild(script);
会有报错,原因是正则没有完整切割好S()里的内容,留下一些引号斜杆导致js文件不正确,一一剔除,或者好好写写正则。
便可看到翻译结果,该结果从console复制到b.txt。
④ 将翻译片替换原文
。。。又是一段丑陋的代码,总之能好好替换就行。
Test
public void test4(){
File file = new File("E:\\code\\。。。\\b.txt");
File file2 = new File("E:\\code\\。。。\\a.txt");
File file3 = new File("E:\\code\\。。。\\ck.txt");
BufferedReader reader = null;
BufferedReader reader2 = null;
BufferedReader reader3 = null;
StringBuffer sbf = new StringBuffer();
StringBuffer sbf3 = new StringBuffer();
String[] sbf2 = new String[5935];
int j=0;
try {
reader = new BufferedReader(new FileReader(file));
reader2 = new BufferedReader(new FileReader(file2));
reader3 = new BufferedReader(new FileReader(file3));
String tempStr;
String tempStr2;
String tempStr3;
while ((tempStr = reader.readLine()) != null) {
sbf.append(tempStr);
}
while ((tempStr3 = reader3.readLine()) != null) {
sbf3.append(tempStr3+"\n");
}
while ((tempStr2 = reader2.readLine()) != null) {
sbf2[j++] = tempStr2;
}
reader.close();
reader2.close();
reader3.close();
String s[] = sbf.toString().split("@@@@@");
String str = sbf3.toString();
for (int n=0; n < s.length; n++) {
if(s[n].contains("\"")) {
str = str.replace(sbf2[n], "'" + s[n] + "'");
} else if(s[n].contains("'")) {
str = str.replace(sbf2[n], '"' + s[n] + '"');
} else {
str = str.replace(sbf2[n], "'" + s[n] + "'");
}
}
sbf3 = new StringBuffer(str);
System.err.println(sbf3.toString());
} catch (IOException e) {
e.printStackTrace();
} finally {
if (reader != null) {
try {
reader.close();
} catch (IOException e1) {
e1.printStackTrace();
}
}
}
}
替换后的js通过③的方法测试一下,发现仍有十几来个报错,这个是因为引号嵌套异常。这几个没有有价值的信息,一一替换回原文即可(一般不再报错行而是往报错的上面几行找)。
然后就能得到正确的版本,接着查找限制内容。
■ 免费限制内容
① 大致看下翻译后的js文件
代码被混淆的很难阅读,并且仍然存在不少密文,对于一个前端渣渣来说,极度难受。
第一页就有这段话
This is a demo version of CKFinder 3 Hello fellow cracker! We are
really sad that you are trying to crack our application - we put lots
of effort to create it. + Would you like to get a free CKFinder
license? Feel free to submit your translation!
百度翻译一下
这是CKFinder 3的演示版
你好,伙计们!我们真的很难过,你试图石皮解我们的应用程序-我们付出了很多努力来创建它。
+您想获得免费的CKFinder许可证吗?请随时提交您的翻译!
呃。。。些许尴尬,惭愧,摸摸头,继续。。。
② 免费禁用删除
被禁用了删除功能,并且未曾调用任何的删除接口,说明是前端限制。
全文查找,不存在这行字,说明不在前面翻译的译文里,又或者被二次加密了,只能通过查看删除的elements,大致定位弹窗的代码。
<button data-ckf-name="DeleteFiles" title="删除" tabindex="-1" class="ckf-toolbar-item ckf-toolbar-button ckf-toolbar-item-focusable ui-btn ui-icon-ckf-file-delete ui-btn-icon-notext ui-corner-all">删除</button>
获取到关键字段DeleteFiles,统计一下,只有6个,方法一一查看,。。。方法虽少,但是代码艰涩难懂,最后定位到两个方法,一个n是真正的删除方法,一个i是动态追加删除方法。
去除里面的action内容,最后发现n去除了这个删除没反应了。
function n(e) {
e.finder.request('folder:getActive').get('acl').fileDelete && e.data.toolbar.push({
type: 'button',
name: 'DeleteFiles',
priority: 10,
icon: 'ckf-file-delete',
label: e.finder.lang.common.delete,
action: function() {
e.finder.request('files:delete', {
files: e.finder.request('files:getSelected').toArray()
})
}
})
}
接着浏览器打断点看走向什么时候弹窗,浪费了一段时间无功而返。
接着搜索files:delete,只有7个
一一查看
setTimeout,好家伙,就是它了。删!!!
③ 免费上传只能10个文件限制
The number of files per folder after the upload cannot exceed 10 in demo mode.
一回生两回熟,直接搜索’msg’,只有几个,一一查看。
一样,msg后面的内容二次加密,再加上这段代码里面有10,就该敏感的认为它就是限制,方法内的内容,删!!!。
④ 免费每隔几分钟就会弹窗
举一反三,刚才搜索’msg’ 的时候其实已经看见了,删!!!。
⑤ 免费板木又文字
查看elements
<h2 style="margin:-1px auto 0;" class="ui-title" role="heading" aria-level="1">This is a demo version of CKFinder 3</h2>
显式style,直接搜margin:-1px auto 0,轻松找到
<%= message %> 修改, 随便定义一个名字。
完成。
原文js对应的地方
① 直接放出对应位置
省去翻译,直接放出原文js对应的位置
② 免费禁用删除
删!!!
setTimeout(function () {
e.$el.toolbar(e.toolbarOptions), e.$el.toolbar(S(" TRGEQCwINO{MIJF^V")), t.mobile.resetActivePageHeight(), e.$el.attr(S('4QWCY\x14YPZ\x10JP/- "6'), e.name), e.finder.fire(S("&SGFFIM_\x14LBTSGQ"), {
name: e.name,
page: e.page
}, e.finder)
}, 0)
③ 免费上传只能10个文件限制
删!!!
var n = o.request(S(";ZTRZ3{%&0\x0635:,$?")).where({
"view:isFolder": !1
}).length,
c = {};
c[S(";QNY")] = [S("E\0<9"), S("\x17d\x7fclox"), S("\x17el"), S("7LCBKY"), S("(K\\M"), S("&STQ[XI"), S('A16$5"'), S("9\\@M"), S(">X#9847"), S("\x14ddmc`y"), S(";KVIO32"), S("B`g"), S(",VS"), S("-XYIK"), S("\rqs`a*")][S(":V]M")](function (e) {
for (var t = "", n = 0; n < e.length; ++n) t += String.fromCharCode(e.charCodeAt(n) ^ n + 18 & 255);
return t
})[S(".E_X\\")](" "), n + s.length > S("5\x07\x07") && o.request(S("1VZUYYP\x02PT]S"), c);
var d = -(n - S("<\f\x0e"));
d < 0 && (d = 0), s.splice(d, s.length)
④ 免费每隔几分钟就会弹窗
删!!!
window[S("\x11av`\\xc}klzp")](function () {
var e = {};
e[S("*F_J")] = [S(">l !;"), S("1\\H"), "f", S("0R_WQ"), S("<LSD9#! "), S("!JM"), S("!f`kFCO@U"), "4"][S("\x1fM@R")](n)[S("\x19ptus")](" "), t.request(S("@%+\"(*!}!',$"), e)
}, S("\x18**+,-.")), O = !0
⑤ 免费板木又文字
改!!!
template: t._.template(S("\x17$q(;oigsE\x1c\0NEWANF\x13\x07\x1a\\U\x0eNEE]\x13\x04\x0e\x14\t\x04\x1c\x07\x1bQXML!&'ca{zh {t"))
改为
template: t._.template('<h2 style="margin:-1px auto 0;"><%= 到此一游 %></h2>')
最后
这样,即免费完成。