大家都知道,“WolframAlpha”是一个非常好的在线数学查询工具,但是唯一的缺点就是——它并不是免费的。在没有付费的情况下,WolframAlpha的官网还是支持一部分免费查询的,只不过功能有限。(推荐配合GeoGebra官网使用)比如说我很喜欢的(作弊用到的 )功能“Step-by-step”没有买Pro就不能使用。但是其实这个软件手机上有破解版,然后就用BurpSuite抓了下包分析下它的协议(主要为APP_ID(注:PHP接口使用v1,抓包协议使用v2)),同时结合官网提供的PHP API Libraries(PHP API库)(是真的垃圾什么功能都没有都要我自己写)和我自己添加的功能,写出了一个基本上App上破解版能用的功能都能实现的网页查询版本。
附: Octave似乎也不错,但是我不会用
*** 需要把 podstate 尽量控制在 1 个以内,多数 podstate 可能会发生签名验证错误
不要问我为什么没修这个东西,因为:lg的APP也是这B样
废话不多说,蓝色的东西在这里: Click Here
原本的API代码: Click Here
经过修改优化完善的API代码: Click Here
主要修改: 添加对“state”项的支持,添加对“info”项的支持,增加修改图像大小的功能,增加输出原文本的功能,添加对“definition”项的支持,添加对“source”项的支持,添加支持重复GET请求的功能(别弄到浏览器爆炸就行),添加对“unit”项的支持,增加对“didyoumean”项的支持,修复原有的一些BUG,增加了一些新BUG,等
2021/6/12 让 HTML 变好看了一点
2019/1/12 修复了本来修复过一遍的 bug:由于 urlencode() 不完全导致的编码错误。
2019/2/25 修复了 podstate 无法重复添加至 add 的问题。
2019/x/xx 增加了图像代理功能
2020/2/23 今天发现它挂了,再看看原来 wolframalpha 要求 api 的后面强制带一个 sig 参数,貌似还跟前面的所有参数有关系
(Response:3 Invalid signature)
解包 APP,罐茶它的源代码:
1 2 3 |
public void setSignature(String sig){ this.signature = sig; } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
public String toString() { StringBuffer s = new StringBuffer(600); for (String[] param : getParameters()) { s.append("&"); s.append(param[0]); s.append("="); s.append(param[1]); } if (this.signature != null) { s.append("&sig="); s.append(this.signature); } return s.toString(); } |
在代码中搜索 setSignature()
1 2 3 4 |
private void query_parameters_set(WAQuery query, WAEngine alphaEngine) { // ...... query.setSignature(getMd5Digest(query)); } |
跟进
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
private String getMd5Digest(WAQueryParameters queryParams) { List<String[]> params = queryParams.getParameters(); params.add(new String[]{"appid", this.app.getAppid()}); Collections.sort(params, new ParamComparator()); StringBuilder s = new StringBuilder(600); s.append("vFdeaRwBTVqdc5CL"); for (String[] param : params) { s.append(param[0]); s.append(param[1]); } try { MessageDigest digest = MessageDigest.getInstance("MD5"); digest.update(s.toString().getBytes()); BigInteger hash = new BigInteger(1, digest.digest()); return String.format("%1$032X", new Object[]{hash}); } catch (NoSuchAlgorithmException e) { return ""; } } } |
可以看出是所有参数弄成 List 然后再排序,最后加上 MD5
跟进排序函数
1 2 3 4 5 |
public static class ParamComparator implements Comparator<String[]> { public int compare(String[] p1, String[] p2) { return p1[0].compareTo(p2[0]); } } |
其实就是按照字典序排序
现在只需要把以上功能加进我们的 API 就行啦~~~
(由于 podstate 需要特判,所以代码可能有点c)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 |
private function constructURL ( $input, $otherParams=array(), $additional ) { // construct the API URL $url = "appid=". urlencode( $this->appID ) ."&input=". urlencode($input); foreach ( $otherParams as $key => $value ) { $url .= "&". urlencode( $key ) ."=". urlencode( $value ); } $url .= $additional; // Compute signature $arr=array(); parse_str($url, $arr); $na=array(); foreach($arr as $key => $val) array_push($na, $key); sort($na); $sig='vFdeaRwBTVqdc5CL'; foreach($na as $val) if($val !== 'podstate') $sig.=urlencode($val).urlencode($arr[$val]); else { // Multiple podstates are allowded $dsp=explode('&',$url); foreach($dsp as $val) if(substr($val,0,9) === 'podstate=') { $sig.='podstate'.substr($val,9); //echo '<br>';var_export(substr($val,9));echo '<br>'; } } $sig=strtoupper(md5($sig)); $url.='&sig='.$sig; return $this->APIURL . '?' . $url; } |