@@ -270,10 +270,111 @@ else if ($dopost == 'viewAPI') { | |||||
require_once(DEDEINC.'/typelink/typelink.class.php'); | require_once(DEDEINC.'/typelink/typelink.class.php'); | ||||
$typeid = isset($typeid) ? intval($typeid) : 0; | $typeid = isset($typeid) ? intval($typeid) : 0; | ||||
$tl = new TypeLink($typeid); | $tl = new TypeLink($typeid); | ||||
$phpCode = '<?php | |||||
$typeid = '.$typeid.'; | |||||
$row = 10; | |||||
$timestamp = time(); | $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/bootstrap.min.css"> | ||||
<link rel="stylesheet" href="../static/web/css/admin.css"> | <link rel="stylesheet" href="../static/web/css/admin.css"> | ||||
<style>.admin-td{border-bottom:1px solid #dee2e6!important}</style> | <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="../static/web/js/webajax.js"></script> | ||||
<script src="js/global.js"></script> | <script src="js/global.js"></script> | ||||
</head> | </head> | ||||
@@ -46,6 +48,59 @@ | |||||
</tr> | </tr> | ||||
</table> | </table> | ||||
</form> | </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> | <script> | ||||
function LoadSuns(ctid, tid) { | function LoadSuns(ctid, tid) { | ||||
if ($DE(ctid).innerHTML.length < 10) { | if ($DE(ctid).innerHTML.length < 10) { | ||||
@@ -66,6 +121,20 @@ | |||||
$DE(objname).style.display = "none"; | $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> | </script> | ||||
</body> | </body> | ||||
</html> | </html> |
@@ -98,8 +98,8 @@ class ListView | |||||
)); | )); | ||||
exit; | 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']) { | if ($sign !== $GLOBALS['sign']) { | ||||
echo json_encode(array( | echo json_encode(array( | ||||
"code" => -1, | "code" => -1, | ||||
@@ -78,6 +78,32 @@ class SgListView | |||||
//设置一些全局参数的值 | //设置一些全局参数的值 | ||||
foreach ($GLOBALS['PubFields'] as $k => $v) $this->Fields[$k] = $v; | foreach ($GLOBALS['PubFields'] as $k => $v) $this->Fields[$k] = $v; | ||||
$this->Fields['rsslink'] = $GLOBALS['cfg_cmsurl']."/static/rss/".$this->TypeID.".xml"; | $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'); | SetSysEnv($this->TypeID, $this->Fields['typename'], 0, '', 'list'); | ||||
$this->Fields['typeid'] = $this->TypeID; | $this->Fields['typeid'] = $this->TypeID; | ||||
@@ -88,7 +88,11 @@ trait JsonQueriable | |||||
{ | { | ||||
if (!is_null($file)) { | if (!is_null($file)) { | ||||
if (is_string($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; | $this->_baseContents = $this->_map; | ||||
return true; | return true; | ||||
} | } | ||||
@@ -242,20 +246,39 @@ trait JsonQueriable | |||||
* Read JSON data from file | * Read JSON data from file | ||||
* | * | ||||
* @param string $file | * @param string $file | ||||
* @param string $type | |||||
* @return bool|string|array | * @return bool|string|array | ||||
* @throws FileNotFoundException | * @throws FileNotFoundException | ||||
* @throws InvalidJsonException | * @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); | $json = $this->isJson($data, true); | ||||
if (!$json) { | if (!$json) { | ||||
throw new InvalidJsonException(); | throw new InvalidJsonException(); | ||||
@@ -22,10 +22,10 @@ function lib_jsonq(&$ctag, &$refObj) | |||||
} | } | ||||
if ($typeid > 0) { | if ($typeid > 0) { | ||||
$timestamp = time(); | $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}"; | $u = "tid={$typeid}&mod=1×tamp={$timestamp}&PageNo=1&PageSize={$row}&sign={$sign}"; | ||||
$url = $url."/apps/list.php?{$u}"; | $url = $url."/apps/list.php?{$u}"; | ||||
$path = "$.lists"; | |||||
$path = "lists"; | |||||
} | } | ||||
$key = md5($url); | $key = md5($url); | ||||
try { | try { | ||||
@@ -115,7 +115,7 @@ class TypeUnit | |||||
echo "</td>"; | 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>"; | 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'; | $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_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_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>"; | 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>"; | ||||
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>"; | 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'; | $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_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_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>"; | echo "<a href='catalog_edit.php?id={$id}' title='修改' class='btn btn-light btn-sm'><i class='fa fa-pencil-square'></i></a>"; | ||||