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