@@ -270,10 +270,111 @@ else if ($dopost == 'viewAPI') { | |||
require_once(DEDEINC.'/typelink/typelink.class.php'); | |||
$typeid = isset($typeid) ? intval($typeid) : 0; | |||
$tl = new TypeLink($typeid); | |||
$phpCode = '<?php | |||
$typeid = '.$typeid.'; | |||
$row = 10; | |||
$timestamp = time(); | |||
$sign = sha1($typeid.$timestamp.$tl->TypeInfos['apikey'].'1'.'10'); | |||
$u = "tid={$typeid}&mod=1×tamp={$timestamp}&PageNo=1&PageSize=10&sign={$sign}"; | |||
header('HTTP/1.1 301 Moved Permanently'); | |||
header("Location:../apps/list.php?{$u}"); | |||
$apikey = \''.$tl->TypeInfos['apikey'].'\'; | |||
$sign = md5($typeid.$timestamp.$apikey.\'1\'.$row); | |||
$durl = "'.$cfg_basehost.'/apps/list.php?tid={$typeid}&mod=1×tamp={$timestamp}&PageNo=1&PageSize={$row}&sign={$sign}"; | |||
$data = json_decode(file_get_contents($durl),true); | |||
if ($data[\'code\'] === 0) { | |||
var_dump($data); | |||
} | |||
?>'; | |||
$gocode = 'package main | |||
import ( | |||
"crypto/md5" | |||
"encoding/json" | |||
"fmt" | |||
"io/ioutil" | |||
"net/http" | |||
"strconv" | |||
"time" | |||
) | |||
func main() { | |||
typeid := '.$typeid.' | |||
row := 10 | |||
timestamp := strconv.FormatInt(time.Now().Unix(), 10) | |||
apikey := "'.$tl->TypeInfos['apikey'].'" | |||
sign := fmt.Sprintf("%x", md5.Sum([]byte(fmt.Sprintf("%d%s%s%d%d", typeid, timestamp, apikey, 1, row)))) | |||
durl := fmt.Sprintf("'.$cfg_basehost.'/apps/list.php?tid=%d&mod=1×tamp=%s&PageNo=1&PageSize=%d&sign=%s", typeid, timestamp, row, sign) | |||
resp, err := http.Get(durl) | |||
if err != nil { | |||
fmt.Println(err) | |||
return | |||
} | |||
defer resp.Body.Close() | |||
body, err := ioutil.ReadAll(resp.Body) | |||
if err != nil { | |||
fmt.Println(err) | |||
return | |||
} | |||
var data map[string]interface{} | |||
if err := json.Unmarshal(body, &data); err != nil { | |||
fmt.Println(err) | |||
return | |||
} | |||
if data["code"].(float64) == 0 { | |||
fmt.Printf("%+v", data) | |||
} | |||
}'; | |||
$pythoncode = 'import hashlib | |||
import json | |||
import time | |||
import urllib.request | |||
typeid = '.$typeid.' | |||
row = 10 | |||
timestamp = int(time.time()) | |||
apikey = \''.$tl->TypeInfos['apikey'].'\' | |||
sign = hashlib.md5((str(typeid) + str(timestamp) + apikey + \'1\' + str(row)).encode()).hexdigest() | |||
durl = f"'.$cfg_basehost.'/apps/list.php?tid={typeid}&mod=1×tamp={timestamp}&PageNo=1&PageSize={row}&sign={sign}" | |||
with urllib.request.urlopen(durl) as url: | |||
data = json.loads(url.read().decode()) | |||
if data[\'code\'] == 0: | |||
print(data) | |||
'; | |||
$jscode = 'const crypto = require(\'crypto\'); | |||
const http = require(\'http\'); | |||
const typeid = '.$typeid.'; | |||
const row = 10; | |||
const timestamp = Math.floor(Date.now() / 1000); | |||
const apikey = \''.$tl->TypeInfos['apikey'].'\'; | |||
const sign = crypto.createHash(\'md5\').update(typeid.toString() + timestamp.toString() + apikey + \'1\' + row.toString()).digest(\'hex\'); | |||
const durl = `'.$cfg_basehost.'/apps/list.php?tid=${typeid}&mod=1×tamp=${timestamp}&PageNo=1&PageSize=${row}&sign=${sign}` | |||
http.get(durl, (res) => { | |||
let data = \'\'; | |||
res.on(\'data\', (chunk) => { | |||
data += chunk; | |||
}); | |||
res.on(\'end\', () => { | |||
console.log(data); | |||
const result = JSON.parse(data); | |||
if (result.code === 0) { | |||
console.log(result); | |||
} | |||
}); | |||
}).on(\'error\', (err) => { | |||
console.log(err); | |||
});'; | |||
$tagcode = '<ul> | |||
{dede:jsonq url="'.$cfg_basehost.'" row="10" typeid='.$typeid.' apikey="'.$tl->TypeInfos['apikey'].'"} | |||
<li><a href="[field:arcurl/]">[field:title/]</a></li> | |||
{/dede:jsonq} | |||
</ul>'; | |||
echo json_encode(array( | |||
"code"=>0, | |||
"data"=>array( | |||
"phpcode"=>htmlspecialchars($phpCode), | |||
"gocode"=>htmlspecialchars($gocode), | |||
"pythoncode"=>htmlspecialchars($pythoncode), | |||
"jscode"=>htmlspecialchars($jscode), | |||
"tagcode"=>htmlspecialchars($tagcode), | |||
) | |||
)); | |||
} | |||
?> |
@@ -8,6 +8,8 @@ | |||
<link rel="stylesheet" href="../static/web/css/bootstrap.min.css"> | |||
<link rel="stylesheet" href="../static/web/css/admin.css"> | |||
<style>.admin-td{border-bottom:1px solid #dee2e6!important}</style> | |||
<script src="../static/web/js/jquery.min.js"></script> | |||
<script src="../static/web/js/bootstrap.min.js"></script> | |||
<script src="../static/web/js/webajax.js"></script> | |||
<script src="js/global.js"></script> | |||
</head> | |||
@@ -46,6 +48,59 @@ | |||
</tr> | |||
</table> | |||
</form> | |||
<div id="mdlViewAPI" class="modal fade" tabindex="-1" aria-hidden="true"> | |||
<div class="modal-dialog modal-xl"> | |||
<div class="modal-content"> | |||
<div class="modal-header"> | |||
<h5 class="modal-title">跨站调用</h5> | |||
<button type="button" class="update-close" data-dismiss="modal" aria-label="Close"><i class="fa fa-times"></i></button> | |||
</div> | |||
<div class="modal-body"> | |||
<form> | |||
<div class="form-group"> | |||
<span> | |||
本功能主要用于移动客户端或第三方系统调用栏目数据进行展现。 | |||
</span> | |||
</div> | |||
<div class="form-group"> | |||
<label for="iptAPICode">代码调用</label> | |||
<nav> | |||
<div class="nav nav-tabs" id="nav-tab" role="tablist"> | |||
<button class="nav-link active" id="nav-php-tab" data-toggle="tab" data-target="#nav-php" type="button" role="tab" aria-controls="nav-php" aria-selected="true">PHP</button> | |||
<button class="nav-link" id="nav-js-tab" data-toggle="tab" data-target="#nav-js" type="button" role="tab" aria-controls="nav-js" aria-selected="true">Javasctipt</button> | |||
<button class="nav-link" id="nav-go-tab" data-toggle="tab" data-target="#nav-go" type="button" role="tab" aria-controls="nav-go" aria-selected="false">Go</button> | |||
<button class="nav-link" id="nav-python-tab" data-toggle="tab" data-target="#nav-python" type="button" role="tab" aria-controls="nav-python" aria-selected="false">Python3</button> | |||
</div> | |||
</nav> | |||
<div class="tab-content py-3" id="nav-tabContent"> | |||
<div class="tab-pane fade show active" id="nav-php" role="tabpanel" aria-labelledby="nav-php-tab"> | |||
<pre><code id="codephp"></code></pre></div> | |||
<div class="tab-pane fade" id="nav-js" role="tabpanel" aria-labelledby="nav-js-tab"> | |||
<pre><code id="codejs"></code></pre> | |||
</div> | |||
<div class="tab-pane fade" id="nav-go" role="tabpanel" aria-labelledby="nav-go-tab"> | |||
<pre><code id="codego"></code></pre> | |||
</div> | |||
<div class="tab-pane fade" id="nav-python" role="tabpanel" aria-labelledby="nav-python-tab"> | |||
<pre><code id="codepython"></code></pre> | |||
</div> | |||
</div> | |||
</div> | |||
<div class="form-group"> | |||
<label for="iptAPITag">标签调用</label> | |||
<pre><code id="codetag"></code></pre> | |||
</div> | |||
</form> | |||
</div> | |||
<div class="modal-footer"> | |||
<div class="btnStep"> | |||
<button id="btnGoStep4" type="button" class="btn btn-success">我知道了</button> | |||
</div> | |||
</div> | |||
</div> | |||
</div> | |||
</div> | |||
<script> | |||
function LoadSuns(ctid, tid) { | |||
if ($DE(ctid).innerHTML.length < 10) { | |||
@@ -66,6 +121,20 @@ | |||
$DE(objname).style.display = "none"; | |||
} | |||
} | |||
function showAPI(tid) { | |||
fetch('catalog_do.php?dopost=viewAPI&typeid=' + tid).then(resp => resp.text()).then((d) => { | |||
let data = JSON.parse(d); | |||
if (data.code == 0) { | |||
$("#codephp").html(data.data.phpcode); | |||
$("#codego").html(data.data.gocode); | |||
$("#codepython").html(data.data.pythoncode); | |||
$("#codejs").html(data.data.jscode); | |||
$("#codetag").html(data.data.tagcode); | |||
$("#mdlViewAPI").modal('show'); | |||
} | |||
}); | |||
} | |||
</script> | |||
</body> | |||
</html> |
@@ -98,8 +98,8 @@ class ListView | |||
)); | |||
exit; | |||
} | |||
//验签算法 sha1(typeid+timestamp+apikey+PageNo+PageSize) | |||
$sign = sha1($this->TypeID.$GLOBALS['timestamp'].$this->Fields['apikey'].$GLOBALS['PageNo'].$GLOBALS['PageSize']); | |||
//验签算法 md5(typeid+timestamp+apikey+PageNo+PageSize) | |||
$sign = md5($this->TypeID.$GLOBALS['timestamp'].$this->Fields['apikey'].$GLOBALS['PageNo'].$GLOBALS['PageSize']); | |||
if ($sign !== $GLOBALS['sign']) { | |||
echo json_encode(array( | |||
"code" => -1, | |||
@@ -78,6 +78,32 @@ class SgListView | |||
//设置一些全局参数的值 | |||
foreach ($GLOBALS['PubFields'] as $k => $v) $this->Fields[$k] = $v; | |||
$this->Fields['rsslink'] = $GLOBALS['cfg_cmsurl']."/static/rss/".$this->TypeID.".xml"; | |||
//API相关逻辑处理 | |||
if ($this->mod == 1 && empty($this->Fields['apikey'])) { | |||
echo json_encode(array( | |||
"code" => -1, | |||
"msg" => "api key is empty", | |||
)); | |||
exit; | |||
} | |||
if($this->mod == 1){ | |||
if (empty($GLOBALS['sign'])) { | |||
echo json_encode(array( | |||
"code" => -1, | |||
"msg" => "sign is empty", | |||
)); | |||
exit; | |||
} | |||
//验签算法 md5(typeid+timestamp+apikey+PageNo+PageSize) | |||
$sign = md5($this->TypeID.$GLOBALS['timestamp'].$this->Fields['apikey'].$GLOBALS['PageNo'].$GLOBALS['PageSize']); | |||
if ($sign !== $GLOBALS['sign']) { | |||
echo json_encode(array( | |||
"code" => -1, | |||
"msg" => "sign check failed", | |||
)); | |||
exit; | |||
} | |||
} | |||
//设置环境变量 | |||
SetSysEnv($this->TypeID, $this->Fields['typename'], 0, '', 'list'); | |||
$this->Fields['typeid'] = $this->TypeID; | |||
@@ -88,7 +88,11 @@ trait JsonQueriable | |||
{ | |||
if (!is_null($file)) { | |||
if (is_string($file)) { | |||
$this->_map = $this->getDataFromFile($file); | |||
if (preg_match("#^http#", $file)) { | |||
$this->_map = $this->getDataFromUrl($file); | |||
} else { | |||
$this->_map = $this->getDataFromFile($file); | |||
} | |||
$this->_baseContents = $this->_map; | |||
return true; | |||
} | |||
@@ -242,20 +246,39 @@ trait JsonQueriable | |||
* Read JSON data from file | |||
* | |||
* @param string $file | |||
* @param string $type | |||
* @return bool|string|array | |||
* @throws FileNotFoundException | |||
* @throws InvalidJsonException | |||
*/ | |||
protected function getDataFromFile($file, $type = 'application/json') | |||
protected function getDataFromFile($file) | |||
{ | |||
$data = file_get_contents($file); | |||
$json = $this->isJson($data, true); | |||
if (!$json) { | |||
throw new InvalidJsonException(); | |||
} | |||
return $json; | |||
} | |||
/** | |||
* Get JSON data from url | |||
* | |||
* @param string $url | |||
* @return bool|string|array | |||
* @throws FileNotFoundException | |||
* @throws InvalidJsonException | |||
*/ | |||
protected function getDataFromUrl($url) | |||
{ | |||
$opts = [ | |||
'http' => [ | |||
'header' => 'Content-Type: '.$type.'; charset=utf-8', | |||
], | |||
]; | |||
$context = stream_context_create($opts); | |||
$data = file_get_contents($file, 0, $context); | |||
$curl_handle=curl_init(); | |||
curl_setopt($curl_handle, CURLOPT_URL, $url); | |||
curl_setopt($curl_handle, CURLOPT_CONNECTTIMEOUT, 2); | |||
curl_setopt($curl_handle, CURLOPT_RETURNTRANSFER, 1); | |||
curl_setopt($curl_handle, CURLOPT_TIMEOUT, 5); | |||
curl_setopt($curl_handle, CURLOPT_MAXREDIRS, 10 ); | |||
curl_setopt($curl_handle, CURLOPT_USERAGENT, 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/112.0.0.0 Safari/537.36'); | |||
$data = curl_exec($curl_handle); | |||
curl_close($curl_handle); | |||
$json = $this->isJson($data, true); | |||
if (!$json) { | |||
throw new InvalidJsonException(); | |||
@@ -22,10 +22,10 @@ function lib_jsonq(&$ctag, &$refObj) | |||
} | |||
if ($typeid > 0) { | |||
$timestamp = time(); | |||
$sign = sha1($typeid.$timestamp.$apikey.'1'.'10'); | |||
$sign = md5($typeid.$timestamp.$apikey.'1'.$row); | |||
$u = "tid={$typeid}&mod=1×tamp={$timestamp}&PageNo=1&PageSize={$row}&sign={$sign}"; | |||
$url = $url."/apps/list.php?{$u}"; | |||
$path = "$.lists"; | |||
$path = "lists"; | |||
} | |||
$key = md5($url); | |||
try { | |||
@@ -115,7 +115,7 @@ class TypeUnit | |||
echo "</td>"; | |||
echo "<td align='right'><a href='{$GLOBALS['cfg_phpurl']}/list.php?tid={$id}' target='_blank' title='预览' class='btn btn-light btn-sm'><i class='fa fa-eye'></i></a>"; | |||
$apidisabled = $row->apienabled == 1? '' : ' disabled'; | |||
echo "<a href='catalog_do.php?dopost=viewAPI&typeid={$id}' target='_blank' title='接口' class='btn btn-light btn-sm{$apidisabled}'><i class='fa fa-bolt'></i></a>"; | |||
echo "<a href='javascript:showAPI({$id})' title='跨站' class='btn btn-light btn-sm{$apidisabled}'><i class='fa fa-bolt'></i></a>"; | |||
echo "<a href='catalog_do.php?cid={$id}&dopost=listArchives' title='文档' class='btn btn-light btn-sm'><i class='fa fa-file-text'></i></a>"; | |||
echo "<a href='catalog_add.php?id={$id}' title='添加' class='btn btn-light btn-sm'><i class='fa fa-plus-circle'></i></a>"; | |||
echo "<a href='catalog_edit.php?id={$id}' title='修改' class='btn btn-light btn-sm'><i class='fa fa-pencil-square'></i></a>"; | |||
@@ -200,7 +200,7 @@ class TypeUnit | |||
echo "</td>"; | |||
echo "<td align='right'><a href='{$GLOBALS['cfg_phpurl']}/list.php?tid={$id}' target='_blank' title='预览' class='btn btn-light btn-sm'><i class='fa fa-eye'></i></a>"; | |||
$apidisabled = $row->apienabled == 1? '' : ' disabled'; | |||
echo "<a href='catalog_do.php?dopost=viewAPI&typeid={$id}' target='_blank' title='接口' class='btn btn-light btn-sm{$apidisabled}'><i class='fa fa-bolt'></i></a>"; | |||
echo "<a href='javascript:showAPI({$id})' title='跨站' class='btn btn-light btn-sm{$apidisabled}'><i class='fa fa-bolt'></i></a>"; | |||
echo "<a href='catalog_do.php?cid={$id}&dopost=listArchives' title='文档' class='btn btn-light btn-sm'><i class='fa fa-file-text'></i></a>"; | |||
echo "<a href='catalog_add.php?id={$id}' title='添加' class='btn btn-light btn-sm'><i class='fa fa-plus-circle'></i></a>"; | |||
echo "<a href='catalog_edit.php?id={$id}' title='修改' class='btn btn-light btn-sm'><i class='fa fa-pencil-square'></i></a>"; | |||