安卓(linux)百度音乐下载乱码的问题
最近几天通过手机浏览百度网页,进入音乐下载低质音频出现了乱码的问题。而之前则不会出现这个问题。猜测:百度最近推出了百度音乐下载,为了提升百度音乐客户端的占有率除非老的低质音频,其他的音频均必须安装音乐客户端才能下载。如下图所示:
对比在此变化之前安卓浏览器下载音乐并不会出现乱码。而之后通过客户端也不会出现乱码。 (⊙ˍ⊙)
分析
通过抓包,发现普通下载的文件名被转成了汉字内码的8进制表示,如下图所示:
这些字符在转化后变成了乱码,而客户端却不会出现这个问题,原因是客户端并没有使用content-disposition的形式下载,而是使用了json,而且数据中的名称传输使用了escape形式的unicode (。_。),如下图所示:
综上,不清楚是不是百度对普通下载的传值做了修改,对比了小米、联想、nexus4等等多种机器,凡是webkit的内核基本都是乱码(linux下火狐模拟mobile也是)。可见要修改正确这个问题必须在browser的downloadHandler中拦截filename的解析,做出正确的解析才行。
原理
通过如下代码(java)可以获取到汉字内码的八进制表示,得以复现content-disposition中的内容:
将上述过程逆向即可获取到正确的文件名。最终的代码及结果如下所示:
import java.net.URLDecoder;
import java.net.URLEncoder;
public class test2 {
public static void main(String[] args) throws Exception {
decode();
encode();
}
private static void encode() {
String str = "";
try {
str = URLEncoder.encode("千千阙歌", "GBK");
System.out.println(str);
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
String[] s = str.substring(1).split("%");
StringBuffer s8 = new StringBuffer();
for(int i=0;i<s.length;i++){
s8.append("\"+Integer.toOctalString(Integer.valueOf(s[i],16)));
}
System.out.println(s8.toString());
}
private static void decode() {
StringBuffer s8 = new StringBuffer("\\307\\247\\307\\247\\343\\332\\270\\350");
String[] s = s8.toString().substring(1).split("\\\");
String str = "";
String result = "";
for (int i=0; i<s.length; i++) {
str += "%"+Integer.toHexString(Integer.valueOf(s[i],8));
}
System.out.println(str);
try {
result = URLDecoder.decode(str, "GBK");
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
System.out.println(result);
System.out.println(s8.toString());
}
}
附件下载:
在webkit中将gbk的string转化为utf-8即可修正。如下图所示:
1. external/webkit/Source/WebKit/android/jni/WebCoreFrameBridge.cpp添加如下函数:
2. 修改downloadStart函数,对jContentDisposition做判断处理,如下图所示:
3. 在头文件添加声明,如下图所示:
重新编译libwebcore.so,push进system/lib重启即可验证。
评论:2