| @@ -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>"; | ||||