| @@ -16,9 +16,6 @@ if (preg_match("#PHP (.*) Development Server#", $_SERVER['SERVER_SOFTWARE'])) { | |||
| } | |||
| require_once(dirname(__FILE__)."/config.php"); | |||
| require_once(DEDEINC.'/dedetag.class.php'); | |||
| $defaultIcoFile = DEDEDATA.'/admin/quickmenu.txt'; | |||
| $myIcoFile = DEDEDATA.'/admin/quickmenu-'.$cuserLogin->getUserID().'.txt'; | |||
| if (!file_exists($myIcoFile)) $myIcoFile = $defaultIcoFile; | |||
| require(DEDEADMIN.'/inc/inc_menu_map.php'); | |||
| include(DEDEADMIN.'/templets/index.htm'); | |||
| exit(); | |||
| @@ -11,9 +11,6 @@ | |||
| require(dirname(__FILE__).'/config.php'); | |||
| require(DEDEINC.'/image.func.php'); | |||
| require(DEDEINC.'/dedetag.class.php'); | |||
| $defaultIcoFile = DEDEDATA.'/admin/quickmenu.txt'; | |||
| $myIcoFile = DEDEDATA.'/admin/quickmenu-'.$cuserLogin->getUserID().'.txt'; | |||
| if (!file_exists($myIcoFile)) $myIcoFile = $defaultIcoFile; | |||
| //默认主页 | |||
| if (empty($dopost)) { | |||
| require(DEDEINC.'/inc/inc_fun_funAdmin.php'); | |||
| @@ -30,92 +27,6 @@ if (empty($dopost)) { | |||
| include DedeInclude('templets/index_body.htm'); | |||
| exit(); | |||
| } | |||
| /*----------------------- | |||
| 增加新项 | |||
| function _AddNew() { } | |||
| -------------------------*/ | |||
| else if ($dopost == 'addnew') { | |||
| if (empty($link) || empty($title)) { | |||
| ShowMsg("链接网址或标题不能为空", "-1"); | |||
| exit(); | |||
| } | |||
| $fp = fopen($myIcoFile, 'r'); | |||
| $oldct = trim(fread($fp, filesize($myIcoFile))); | |||
| fclose($fp); | |||
| $link = preg_replace("#['\"]#", '`', $link); | |||
| $title = preg_replace("#['\"]#", '`', $title); | |||
| $ico = preg_replace("#['\"]#", '`', $ico); | |||
| $oldct .= "\r\n<menu:item ico=\"{$ico}\" link=\"{$link}\" title=\"{$title}\">"; | |||
| $myIcoFileTrue = DEDEDATA.'/admin/quickmenu-'.$cuserLogin->getUserID().'.txt'; | |||
| $fp = fopen($myIcoFileTrue, 'w'); | |||
| fwrite($fp, $oldct); | |||
| fclose($fp); | |||
| ShowMsg("成功增加一个项目", "index_body.php?".time()); | |||
| exit(); | |||
| } | |||
| /*--------------------------- | |||
| 保存修改的项 | |||
| function _EditSave() { } | |||
| ----------------------------*/ | |||
| else if ($dopost == 'editsave') { | |||
| $quickmenu = stripslashes($quickmenu); | |||
| $myIcoFileTrue = DEDEDATA.'/admin/quickmenu-'.$cuserLogin->getUserID().'.txt'; | |||
| $fp = fopen($myIcoFileTrue, 'w'); | |||
| fwrite($fp, $quickmenu); | |||
| fclose($fp); | |||
| ShowMsg("成功修改快捷操作项目", "index_body.php?".time()); | |||
| exit(); | |||
| } | |||
| /*--------------------------- | |||
| 保存修改的项 | |||
| function _EditSave() { } | |||
| ----------------------------*/ | |||
| else if ($dopost == 'movesave') { | |||
| $movedata = str_replace('\\', "", $sortorder); | |||
| $movedata = json_decode($movedata, TRUE); | |||
| $movedata = serialize($movedata); | |||
| $myIcoFileTrue = DEDEDATA.'/admin/move-'.$cuserLogin->getUserID().'.txt'; | |||
| $fp = fopen($myIcoFileTrue, 'w'); | |||
| fwrite($fp, $movedata); | |||
| fclose($fp); | |||
| } | |||
| /*----------------------------- | |||
| 显示修改表单 | |||
| function _EditShow() { } | |||
| -----------------------------*/ | |||
| else if ($dopost == 'editshow') { | |||
| $fp = fopen($myIcoFile, 'r'); | |||
| $oldct = trim(fread($fp, filesize($myIcoFile))); | |||
| fclose($fp); | |||
| ?> | |||
| <form name="editform" action="index_body.php" method="post"> | |||
| <input type="hidden" name="dopost" value="editsave"> | |||
| <table width="100%" border="0" cellspacing="0" cellpadding="0"> | |||
| <tr> | |||
| <td height="30" background="images/tbg.gif"> | |||
| <div style="float:left;margin-left:10px">修改快捷操作项</div> | |||
| <div style="float:right;padding:2px 10px 0 0"> | |||
| <a href="javascript:CloseTab('editTab')"><img src="images/close.gif"></a> | |||
| </div> | |||
| </td> | |||
| </tr> | |||
| <tr> | |||
| <td style="height:10px;border-top:1px solid #8DA659"></td> | |||
| </tr> | |||
| <tr> | |||
| <td align="center"><textarea name="quickmenu" rows="10" cols="50"><?php echo $oldct; ?></textarea></td> | |||
| </tr> | |||
| <tr> | |||
| <td height="36" align="center"> | |||
| <input type="submit" name="Submit" value="保存项目" class="np coolbg" style="width:80px;cursor:pointer"> | |||
| <input type="reset" name="reset" value="重设" class="np coolbg" style="width:50px;cursor:pointer"> | |||
| </td> | |||
| </tr> | |||
| </table> | |||
| </form> | |||
| <?php | |||
| exit(); | |||
| } | |||
| /*--------------------------------- | |||
| 载入右边内容 | |||
| function _getRightSide() { } | |||
| @@ -247,5 +158,17 @@ exit; | |||
| )); | |||
| } | |||
| } | |||
| } | |||
| } elseif ($dopost == 'get_statistics') { | |||
| require_once(DEDEINC."/libraries/statistics.class.php"); | |||
| //获取统计信息 | |||
| $sdate = empty($sdate) ? 0 : intval($sdate); | |||
| $stat = new DedeStatistics; | |||
| $rs = $stat->GetInfoByDate($sdate); | |||
| echo json_encode(array( | |||
| "code" => 200, | |||
| "msg" => "", | |||
| "result" => $rs, | |||
| )); | |||
| exit; | |||
| } | |||
| ?> | |||
| @@ -90,25 +90,6 @@ | |||
| <iframe src="index_body.php" id="main" name="main" frameborder="0"></iframe> | |||
| </div> | |||
| </div> | |||
| <div class="qucikmenu" id="qucikmenu"> | |||
| <ul> | |||
| <?php | |||
| $dtp = new DedeTagparse(); | |||
| $dtp->SetNameSpace('menu','<','>'); | |||
| $dtp->LoadTemplet($myIcoFile); | |||
| if(is_array($dtp->CTags)) | |||
| { | |||
| foreach($dtp->CTags as $ctag) | |||
| { | |||
| $title = $ctag->GetAtt('title'); | |||
| $ico = $ctag->GetAtt('ico'); | |||
| $link = $ctag->GetAtt('link'); | |||
| echo "<li><a target='main' href='{$link}'>{$title}</a></li>"; | |||
| } | |||
| } | |||
| ?> | |||
| </ul> | |||
| </div> | |||
| <script> | |||
| function JumpFrame(url1, url2) { | |||
| jQuery('#menufra').get(0).src = url1; | |||
| @@ -12,18 +12,74 @@ | |||
| <script src="../static/js/jquery.js"></script> | |||
| <script src="../static/js/bootstrap.bundle.js"></script> | |||
| <script src="../static/js/webajax.js"></script> | |||
| <script src="../static/js/chart.min.js"></script> | |||
| <script src="js/indexbody.js"></script> | |||
| <script src="js/main.js"></script> | |||
| <style> | |||
| .row{display:flex;flex-wrap:wrap} | |||
| .row>[class*='col-']{display:flex;flex-direction:column} | |||
| .table{margin-bottom:0} | |||
| .stattable{width: 100%;} | |||
| table.stattable td { | |||
| padding: 0 5px; | |||
| height: 25px; | |||
| line-height: 25px; | |||
| border-bottom: 1px solid #f0f0f0; | |||
| font-size: 12px; | |||
| text-align: right; | |||
| } | |||
| table.stattable td.today { | |||
| font-size: 12px; | |||
| color: #000; | |||
| height: 25px; | |||
| line-height: 25px; | |||
| font-weight: 700; | |||
| } | |||
| </style> | |||
| </head> | |||
| <body> | |||
| <div class="container-fluid"> | |||
| <div class="row"> | |||
| <div id="__testEvn" class="col-md-12"></div> | |||
| <div class="col-md-12 mt-3"> | |||
| <div class="card"> | |||
| <div class="card-header">流量统计 <a title="点击查看流量统计图" href="#statChart"><i class="fa fa-line-chart" aria-hidden="true"></i></a></div> | |||
| <div class="card-body"> | |||
| <table class="stattable"> | |||
| <tbody> | |||
| <tr class="title"> | |||
| <td width="10%"></td> | |||
| <td width="20%">浏览次数(PV)</td> | |||
| <td width="20%">独立访客(UV)</td> | |||
| <td width="20%">IP</td> | |||
| <td width="18%" >访问次数</td> | |||
| </tr> | |||
| <tr class="bg-white"> | |||
| <td class="today">今日</td> | |||
| <td class="today" id="today_pv">...</td> | |||
| <td class="today" id="today_uv">...</td> | |||
| <td class="today" id="today_ip">...</td> | |||
| <td class="today" id="today_vv">...</td> | |||
| </tr> | |||
| <tr class="bg-white"> | |||
| <td class="">昨日</td> | |||
| <td id="yestoday_pv">...</td> | |||
| <td id="yestoday_uv">...</td> | |||
| <td id="yestoday_ip">...</td> | |||
| <td id="yestoday_vv">...</td> | |||
| </tr> | |||
| <tr class="bg-white grey9 hide" style="display: table-row;"> | |||
| <td class="">历史累计</td> | |||
| <td id="total_pv">...</td> | |||
| <td id="total_uv">...</td> | |||
| <td id="total_ip">...</td> | |||
| <td id="total_vv">...</td> | |||
| </tr> | |||
| </tbody> | |||
| </table> | |||
| </div> | |||
| </div> | |||
| </div> | |||
| <div class="col-md-6 mt-3 updatenews"> | |||
| <div class="card"> | |||
| <div class="card-header">更新消息</div> | |||
| @@ -44,27 +100,6 @@ | |||
| <div class="card-body" id="_systeminfo">正在载入</div> | |||
| </div> | |||
| </div> | |||
| <div class="col-md-6 mt-3"> | |||
| <div class="card"> | |||
| <div class="card-header">快捷操作<span class="float-right"><a href="javascript:AddNew()" class="btn btn-success btn-sm">新增</a><a href="javascript:ListAll()" class="btn btn-success btn-sm">管理</a></span></div> | |||
| <div class="card-body"> | |||
| <ul class="nav"> | |||
| <?php | |||
| $dtp = new DedeTagparse(); | |||
| $dtp->SetNameSpace('menu','<','>'); | |||
| $dtp->LoadTemplet($myIcoFile); | |||
| if(is_array($dtp->CTags)){ | |||
| foreach($dtp->CTags as $ctag){ | |||
| $title = $ctag->GetAtt('title'); | |||
| $link = $ctag->GetAtt('link'); | |||
| echo "<a href='{$link}' class='btn btn-success btn-sm'>{$title}</a>"; | |||
| } | |||
| } | |||
| ?> | |||
| </ul> | |||
| </div> | |||
| </div> | |||
| </div> | |||
| <div class="col-md-6 mt-3"> | |||
| <div class="card"> | |||
| <div class="card-header">信息统计</div> | |||
| @@ -138,9 +173,17 @@ | |||
| </div> | |||
| </div> | |||
| </div> | |||
| <div class="col-md-6 mt-3"> | |||
| <div class="card"> | |||
| <div class="card-header"><a name="statChart">流量统计图</a></div> | |||
| <div class="card-body"> | |||
| <canvas id="statChart" style="height: 260px;"></canvas> | |||
| </div> | |||
| </div> | |||
| </div> | |||
| </div> | |||
| </div> | |||
| <div class="footer"> | |||
| <div class="footer mt-2"> | |||
| <div id="loaddiv" style="display:none"> | |||
| <p align="center"><img src="images/loadinglit.gif">请稍后,正在下载更新文件列表</p> | |||
| </div> | |||
| @@ -188,6 +231,21 @@ | |||
| }); | |||
| </script> | |||
| <script> | |||
| Date.prototype.Format = function (fmt) { //author: meizz | |||
| var o = { | |||
| "M+": this.getMonth() + 1, //月份 | |||
| "d+": this.getDate(), //日 | |||
| "h+": this.getHours(), //小时 | |||
| "m+": this.getMinutes(), //分 | |||
| "s+": this.getSeconds(), //秒 | |||
| "q+": Math.floor((this.getMonth() + 3) / 3), //季度 | |||
| "S": this.getMilliseconds() //毫秒 | |||
| }; | |||
| if (/(y+)/.test(fmt)) fmt = fmt.replace(RegExp.$1, (this.getFullYear() + "").substr(4 - RegExp.$1.length)); | |||
| for (var k in o) | |||
| if (new RegExp("(" + k + ")").test(fmt)) fmt = fmt.replace(RegExp.$1, (RegExp.$1.length == 1) ? (o[k]) : (("00" + o[k]).substr(("" + o[k]).length))); | |||
| return fmt; | |||
| } | |||
| var dedebizInfo; | |||
| function ViewDedeBIZ(){ | |||
| console.log(dedebizInfo); | |||
| @@ -280,11 +338,128 @@ | |||
| } | |||
| }); | |||
| } | |||
| function LoadStat() { | |||
| $.get("index_body.php?dopost=get_statistics", function(data){ | |||
| let rsp = JSON.parse(data); | |||
| if (rsp.code == 200) { | |||
| var tpv = parseInt(rsp.result.pv); | |||
| var tuv = parseInt(rsp.result.uv); | |||
| var tip = parseInt(rsp.result.ip); | |||
| var tvv = parseInt(rsp.result.vv); | |||
| $("#today_pv").html(tpv); | |||
| $("#today_uv").html(tuv); | |||
| $("#today_ip").html(tip); | |||
| $("#today_vv").html(tvv); | |||
| $.get("index_body.php?dopost=get_statistics&sdate=-1", function(data){ | |||
| let rsp = JSON.parse(data); | |||
| if (rsp.code == 200) { | |||
| $("#total_pv").html(parseInt(rsp.result.pv)+tpv); | |||
| $("#total_uv").html(parseInt(rsp.result.uv)+tuv); | |||
| $("#total_ip").html(parseInt(rsp.result.ip)+tip); | |||
| $("#total_vv").html(parseInt(rsp.result.vv)+tvv); | |||
| } | |||
| }); | |||
| } | |||
| }); | |||
| var d = new Date(); | |||
| d.setDate(d.getDate() - 1); | |||
| var s = d.Format("yyyy-MM-dd"); | |||
| s = s.replaceAll("-",""); | |||
| $.get("index_body.php?dopost=get_statistics&sdate="+s, function(data){ | |||
| let rsp = JSON.parse(data); | |||
| if (rsp.code == 200) { | |||
| $("#yestoday_pv").html(rsp.result.pv); | |||
| $("#yestoday_uv").html(rsp.result.uv); | |||
| $("#yestoday_ip").html(rsp.result.ip); | |||
| $("#yestoday_vv").html(rsp.result.vv); | |||
| } | |||
| }); | |||
| } | |||
| async function LoadStatChart() { | |||
| const ctx = document.getElementById('statChart').getContext('2d'); | |||
| let labels = []; | |||
| let pvs = []; | |||
| let ips = []; | |||
| let uvs = []; | |||
| let vvs = []; | |||
| for (let i = 15; i > 0; i--) { | |||
| var d = new Date(); | |||
| d.setDate(d.getDate() - i); | |||
| var s = d.Format("yyyy-MM-dd"); | |||
| labels.push(d.Format("MM-dd")); | |||
| s = s.replaceAll("-",""); | |||
| let resp = await fetch("index_body.php?dopost=get_statistics&sdate="+s); | |||
| let data = await resp.json(); | |||
| if (data.code == 200) { | |||
| pvs.push(typeof data.result.pv=="undefined"? 0 : data.result.pv); | |||
| ips.push(typeof data.result.ip=="undefined"? 0 : data.result.ip); | |||
| uvs.push(typeof data.result.uv=="undefined"? 0 : data.result.uv); | |||
| vvs.push(typeof data.result.vv=="undefined"? 0 : data.result.vv); | |||
| } | |||
| } | |||
| console.log(pvs); | |||
| console.log(ips); | |||
| console.log(uvs); | |||
| console.log(vvs); | |||
| const myChart = new Chart(ctx, { | |||
| type: 'line', | |||
| options: { | |||
| responsive: true, | |||
| plugins: { | |||
| legend: { | |||
| position: 'top', | |||
| }, | |||
| title: { | |||
| display: true, | |||
| text: '<?php echo $cfg_webname; ?>流量统计图' | |||
| } | |||
| } | |||
| }, | |||
| data: { | |||
| labels: labels, | |||
| datasets: [{ | |||
| label: 'IP', | |||
| data: ips, | |||
| borderColor: 'rgba(255, 99, 132, 1)', | |||
| backgroundColor :'rgba(255, 99, 132, 0.2)', | |||
| borderWidth: 1 | |||
| }, | |||
| { | |||
| label: 'PV', | |||
| data: pvs, | |||
| borderColor: 'rgba(54, 162, 235, 1)', | |||
| backgroundColor :'rgba(54, 162, 235, 0.2)', | |||
| borderWidth: 1 | |||
| },{ | |||
| label: 'UV', | |||
| data: uvs, | |||
| borderColor: 'rgba(255, 206, 86, 1)', | |||
| backgroundColor: 'rgba(255, 206, 86, 0.2)', | |||
| borderWidth: 1 | |||
| },{ | |||
| label: '访问次数', | |||
| data: vvs, | |||
| borderColor: 'rgba(75, 192, 192, 1)', | |||
| backgroundColor: 'rgba(75, 192, 192, 0.2)', | |||
| borderWidth: 1 | |||
| } | |||
| ] | |||
| }, | |||
| }); | |||
| } | |||
| $(document).ready(function(){ | |||
| LoadServer(); | |||
| LoadStat(); | |||
| LoadStatChart(); | |||
| setInterval(function(){ | |||
| LoadServer(); | |||
| }, 5000) | |||
| }, 60000) | |||
| }); | |||
| </script> | |||
| </body> | |||
| @@ -0,0 +1,28 @@ | |||
| <?php | |||
| /** | |||
| * | |||
| * 统计程序 | |||
| * | |||
| * @version $Id: statistics.php$ | |||
| * @package DedeBIZ.Site | |||
| * @copyright Copyright (c) 2022, DedeBIZ.COM | |||
| * @license https://www.dedebiz.com/license | |||
| * @link https://www.dedebiz.com | |||
| */ | |||
| require_once(dirname(__FILE__)."/../system/common.inc.php"); | |||
| require_once(DEDEINC."/libraries/statistics.class.php"); | |||
| if (empty($dopost)) $dopost = ''; | |||
| $stat = new DedeStatistics; | |||
| if ($dopost == "stat") { | |||
| $rs = $stat->Record(); | |||
| $result = array( | |||
| "code" => 200, | |||
| "data" => "success", | |||
| ); | |||
| echo json_encode($result); | |||
| exit; | |||
| } | |||
| $v = $stat->GetStat(); | |||
| echo $v; | |||
| @@ -17,7 +17,7 @@ if(file_exists(INSLOCKFILE)) | |||
| $verMsg = 'V6'; | |||
| $dfDbname = 'DedeBIZ'; | |||
| $cfg_version_detail = '6.1.6'; //详细版本号 | |||
| $cfg_version_detail = '6.1.7beta'; //详细版本号 | |||
| $errmsg = ''; | |||
| if (version_compare(PHP_VERSION, '8.0.0', '>=')) { | |||
| mysqli_report(MYSQLI_REPORT_OFF); | |||
| @@ -50,13 +50,14 @@ class Archives | |||
| */ | |||
| function __construct($aid) | |||
| { | |||
| global $dsql; | |||
| global $dsql,$envs; | |||
| $this->IsError = FALSE; | |||
| $this->ArcID = $aid; | |||
| $this->PreNext = array(); | |||
| $this->dsql = $dsql; | |||
| $query = "SELECT channel,typeid FROM `#@__arctiny` WHERE id='$aid' "; | |||
| $arr = $this->dsql->GetOne($query); | |||
| $envs['url_type'] = 2; | |||
| if (!is_array($arr)) { | |||
| $this->IsError = TRUE; | |||
| } else { | |||
| @@ -50,7 +50,8 @@ class ListView | |||
| */ | |||
| function __construct($typeid, $uppage = 1) | |||
| { | |||
| global $dsql; | |||
| global $dsql,$envs; | |||
| $envs['url_type'] = 1; | |||
| $this->TypeID = $typeid; | |||
| $this->dsql = &$dsql; | |||
| $this->CrossID = ''; | |||
| @@ -76,7 +76,7 @@ class SearchView | |||
| $kwtype = 1, | |||
| $mid = 0 | |||
| ) { | |||
| global $cfg_search_max, $cfg_search_maxrc, $cfg_search_time; | |||
| global $cfg_search_max, $cfg_search_maxrc, $cfg_search_time,$envs; | |||
| if (empty($upagesize)) { | |||
| $upagesize = 10; | |||
| } | |||
| @@ -131,6 +131,8 @@ class SearchView | |||
| if ($this->PageNo == 1) { | |||
| $this->dsql->ExecuteNoneQuery("UPDATE `#@__search_keywords` SET result='".$this->TotalResult."' WHERE keyword='".addslashes($keyword)."'; "); | |||
| } | |||
| $envs['url_type'] = 3; | |||
| $envs['value'] = $keyword; | |||
| } | |||
| //php4构造函数 | |||
| function SearchView( | |||
| @@ -51,7 +51,8 @@ class SgListView | |||
| */ | |||
| function __construct($typeid, $searchArr = array()) | |||
| { | |||
| global $dsql; | |||
| global $dsql,$envs; | |||
| $envs['url_type'] = 1; | |||
| $this->TypeID = $typeid; | |||
| $this->dsql = $dsql; | |||
| $this->CrossID = ''; | |||
| @@ -45,7 +45,7 @@ class TagList | |||
| */ | |||
| function __construct($keyword, $templet) | |||
| { | |||
| global $dsql; | |||
| global $dsql,$envs; | |||
| $this->Templet = $templet; | |||
| $this->Tag = $keyword; | |||
| $this->dsql = $dsql; | |||
| @@ -90,6 +90,8 @@ class TagList | |||
| } | |||
| $this->dtp->LoadTemplate($tempfile); | |||
| $this->TempletsFile = preg_replace("#^".$GLOBALS['cfg_basedir']."#", '', $tempfile); | |||
| $envs['url_type'] = 4; | |||
| $envs['value'] = $keyword; | |||
| } | |||
| function TagPinyinExists($tag) | |||
| { | |||
| @@ -192,7 +192,7 @@ $cfg_soft_dir = $cfg_medias_dir.'/soft'; | |||
| $cfg_other_medias = $cfg_medias_dir.'/media'; | |||
| //软件摘要信息,****请不要删除本项**** 否则系统无法正确接收系统漏洞或升级信息 | |||
| $cfg_version = 'V6'; | |||
| $cfg_version_detail = '6.1.6'; //详细版本号 | |||
| $cfg_version_detail = '6.1.7beta'; //详细版本号 | |||
| $cfg_soft_lang = 'utf-8'; | |||
| $cfg_soft_public = 'base'; | |||
| $cfg_softname = '织梦内容管理系统'; | |||
| @@ -0,0 +1,416 @@ | |||
| <?php | |||
| if (!defined('DEDEINC')) exit('dedebiz'); | |||
| require_once(DEDEINC."/libraries/crawlerdetect.class.php"); | |||
| require_once(DEDEINC."/libraries/mobiledetect.class.php"); | |||
| // copyright https://github.com/jenssegers/agent | |||
| use BadMethodCallException; | |||
| class Agent extends Mobile_Detect | |||
| { | |||
| /** | |||
| * List of desktop devices. | |||
| * @var array | |||
| */ | |||
| protected static $desktopDevices = [ | |||
| 'Macintosh' => 'Macintosh', | |||
| ]; | |||
| /** | |||
| * List of additional operating systems. | |||
| * @var array | |||
| */ | |||
| protected static $additionalOperatingSystems = [ | |||
| 'Windows' => 'Windows', | |||
| 'Windows NT' => 'Windows NT', | |||
| 'OS X' => 'Mac OS X', | |||
| 'Debian' => 'Debian', | |||
| 'Ubuntu' => 'Ubuntu', | |||
| 'Macintosh' => 'PPC', | |||
| 'OpenBSD' => 'OpenBSD', | |||
| 'Linux' => 'Linux', | |||
| 'ChromeOS' => 'CrOS', | |||
| ]; | |||
| /** | |||
| * List of additional browsers. | |||
| * @var array | |||
| */ | |||
| protected static $additionalBrowsers = [ | |||
| 'Opera Mini' => 'Opera Mini', | |||
| 'Opera' => 'Opera|OPR', | |||
| 'Edge' => 'Edge|Edg', | |||
| 'Coc Coc' => 'coc_coc_browser', | |||
| 'UCBrowser' => 'UCBrowser', | |||
| 'Vivaldi' => 'Vivaldi', | |||
| 'Chrome' => 'Chrome', | |||
| 'Firefox' => 'Firefox', | |||
| 'Safari' => 'Safari', | |||
| 'IE' => 'MSIE|IEMobile|MSIEMobile|Trident/[.0-9]+', | |||
| 'Netscape' => 'Netscape', | |||
| 'Mozilla' => 'Mozilla', | |||
| 'WeChat' => 'MicroMessenger', | |||
| ]; | |||
| /** | |||
| * List of additional properties. | |||
| * @var array | |||
| */ | |||
| protected static $additionalProperties = [ | |||
| // Operating systems | |||
| 'Windows' => 'Windows NT [VER]', | |||
| 'Windows NT' => 'Windows NT [VER]', | |||
| 'OS X' => 'OS X [VER]', | |||
| 'BlackBerryOS' => ['BlackBerry[\w]+/[VER]', 'BlackBerry.*Version/[VER]', 'Version/[VER]'], | |||
| 'AndroidOS' => 'Android [VER]', | |||
| 'ChromeOS' => 'CrOS x86_64 [VER]', | |||
| // Browsers | |||
| 'Opera Mini' => 'Opera Mini/[VER]', | |||
| 'Opera' => [' OPR/[VER]', 'Opera Mini/[VER]', 'Version/[VER]', 'Opera [VER]'], | |||
| 'Netscape' => 'Netscape/[VER]', | |||
| 'Mozilla' => 'rv:[VER]', | |||
| 'IE' => ['IEMobile/[VER];', 'IEMobile [VER]', 'MSIE [VER];', 'rv:[VER]'], | |||
| 'Edge' => ['Edge/[VER]', 'Edg/[VER]'], | |||
| 'Vivaldi' => 'Vivaldi/[VER]', | |||
| 'Coc Coc' => 'coc_coc_browser/[VER]', | |||
| ]; | |||
| /** | |||
| * @var CrawlerDetect | |||
| */ | |||
| protected static $crawlerDetect; | |||
| /** | |||
| * Get all detection rules. These rules include the additional | |||
| * platforms and browsers and utilities. | |||
| * @return array | |||
| */ | |||
| public static function getDetectionRulesExtended() | |||
| { | |||
| static $rules; | |||
| if (!$rules) { | |||
| $rules = static::mergeRules( | |||
| static::$desktopDevices, // NEW | |||
| static::$phoneDevices, | |||
| static::$tabletDevices, | |||
| static::$operatingSystems, | |||
| static::$additionalOperatingSystems, // NEW | |||
| static::$browsers, | |||
| static::$additionalBrowsers, // NEW | |||
| static::$utilities | |||
| ); | |||
| } | |||
| return $rules; | |||
| } | |||
| public function getRules() | |||
| { | |||
| if ($this->detectionType === static::DETECTION_TYPE_EXTENDED) { | |||
| return static::getDetectionRulesExtended(); | |||
| } | |||
| return static::getMobileDetectionRules(); | |||
| } | |||
| /** | |||
| * @return CrawlerDetect | |||
| */ | |||
| public function getCrawlerDetect() | |||
| { | |||
| if (static::$crawlerDetect === null) { | |||
| static::$crawlerDetect = new CrawlerDetect(); | |||
| } | |||
| return static::$crawlerDetect; | |||
| } | |||
| public static function getBrowsers() | |||
| { | |||
| return static::mergeRules( | |||
| static::$additionalBrowsers, | |||
| static::$browsers | |||
| ); | |||
| } | |||
| public static function getOperatingSystems() | |||
| { | |||
| return static::mergeRules( | |||
| static::$operatingSystems, | |||
| static::$additionalOperatingSystems | |||
| ); | |||
| } | |||
| public static function getPlatforms() | |||
| { | |||
| return static::mergeRules( | |||
| static::$operatingSystems, | |||
| static::$additionalOperatingSystems | |||
| ); | |||
| } | |||
| public static function getDesktopDevices() | |||
| { | |||
| return static::$desktopDevices; | |||
| } | |||
| public static function getProperties() | |||
| { | |||
| return static::mergeRules( | |||
| static::$additionalProperties, | |||
| static::$properties | |||
| ); | |||
| } | |||
| /** | |||
| * Get accept languages. | |||
| * @param string $acceptLanguage | |||
| * @return array | |||
| */ | |||
| public function languages($acceptLanguage = null) | |||
| { | |||
| if ($acceptLanguage === null) { | |||
| $acceptLanguage = $this->getHttpHeader('HTTP_ACCEPT_LANGUAGE'); | |||
| } | |||
| if (!$acceptLanguage) { | |||
| return []; | |||
| } | |||
| $languages = []; | |||
| // Parse accept language string. | |||
| foreach (explode(',', $acceptLanguage) as $piece) { | |||
| $parts = explode(';', $piece); | |||
| $language = strtolower($parts[0]); | |||
| $priority = empty($parts[1]) ? 1. : floatval(str_replace('q=', '', $parts[1])); | |||
| $languages[$language] = $priority; | |||
| } | |||
| // Sort languages by priority. | |||
| arsort($languages); | |||
| return array_keys($languages); | |||
| } | |||
| /** | |||
| * Match a detection rule and return the matched key. | |||
| * @param array $rules | |||
| * @param string|null $userAgent | |||
| * @return string|bool | |||
| */ | |||
| protected function findDetectionRulesAgainstUA(array $rules, $userAgent = null) | |||
| { | |||
| // Loop given rules | |||
| foreach ($rules as $key => $regex) { | |||
| if (empty($regex)) { | |||
| continue; | |||
| } | |||
| // Check match | |||
| if ($this->match($regex, $userAgent)) { | |||
| return $key ?: reset((array)$this->matchesArray); | |||
| } | |||
| } | |||
| return false; | |||
| } | |||
| /** | |||
| * Get the browser name. | |||
| * @param string|null $userAgent | |||
| * @return string|bool | |||
| */ | |||
| public function browser($userAgent = null) | |||
| { | |||
| return $this->findDetectionRulesAgainstUA(static::getBrowsers(), $userAgent); | |||
| } | |||
| /** | |||
| * Get the platform name. | |||
| * @param string|null $userAgent | |||
| * @return string|bool | |||
| */ | |||
| public function platform($userAgent = null) | |||
| { | |||
| return $this->findDetectionRulesAgainstUA(static::getPlatforms(), $userAgent); | |||
| } | |||
| /** | |||
| * Get the device name. | |||
| * @param string|null $userAgent | |||
| * @return string|bool | |||
| */ | |||
| public function device($userAgent = null) | |||
| { | |||
| $rules = static::mergeRules( | |||
| static::getDesktopDevices(), | |||
| static::getPhoneDevices(), | |||
| static::getTabletDevices(), | |||
| static::getUtilities() | |||
| ); | |||
| return $this->findDetectionRulesAgainstUA($rules, $userAgent); | |||
| } | |||
| /** | |||
| * Check if the device is a desktop computer. | |||
| * @param string|null $userAgent deprecated | |||
| * @param array $httpHeaders deprecated | |||
| * @return bool | |||
| */ | |||
| public function isDesktop($userAgent = null, $httpHeaders = null) | |||
| { | |||
| // Check specifically for cloudfront headers if the useragent === 'Amazon CloudFront' | |||
| if ($this->getUserAgent() === 'Amazon CloudFront') { | |||
| $cfHeaders = $this->getCfHeaders(); | |||
| if(array_key_exists('HTTP_CLOUDFRONT_IS_DESKTOP_VIEWER', $cfHeaders)) { | |||
| return $cfHeaders['HTTP_CLOUDFRONT_IS_DESKTOP_VIEWER'] === 'true'; | |||
| } | |||
| } | |||
| return !$this->isMobile($userAgent, $httpHeaders) && !$this->isTablet($userAgent, $httpHeaders) && !$this->isRobot($userAgent); | |||
| } | |||
| /** | |||
| * Check if the device is a mobile phone. | |||
| * @param string|null $userAgent deprecated | |||
| * @param array $httpHeaders deprecated | |||
| * @return bool | |||
| */ | |||
| public function isPhone($userAgent = null, $httpHeaders = null) | |||
| { | |||
| return $this->isMobile($userAgent, $httpHeaders) && !$this->isTablet($userAgent, $httpHeaders); | |||
| } | |||
| /** | |||
| * Get the robot name. | |||
| * @param string|null $userAgent | |||
| * @return string|bool | |||
| */ | |||
| public function robot($userAgent = null) | |||
| { | |||
| if ($this->getCrawlerDetect()->isCrawler($userAgent ?: $this->userAgent)) { | |||
| return ucfirst($this->getCrawlerDetect()->getMatches()); | |||
| } | |||
| return false; | |||
| } | |||
| /** | |||
| * Check if device is a robot. | |||
| * @param string|null $userAgent | |||
| * @return bool | |||
| */ | |||
| public function isRobot($userAgent = null) | |||
| { | |||
| return $this->getCrawlerDetect()->isCrawler($userAgent ?: $this->userAgent); | |||
| } | |||
| /** | |||
| * Get the device type | |||
| * @param null $userAgent | |||
| * @param null $httpHeaders | |||
| * @return string | |||
| */ | |||
| public function deviceType($userAgent = null, $httpHeaders = null) | |||
| { | |||
| if ($this->isDesktop($userAgent, $httpHeaders)) { | |||
| return "desktop"; | |||
| } elseif ($this->isPhone($userAgent, $httpHeaders)) { | |||
| return "phone"; | |||
| } elseif ($this->isTablet($userAgent, $httpHeaders)) { | |||
| return "tablet"; | |||
| } elseif ($this->isRobot($userAgent)) { | |||
| return "robot"; | |||
| } | |||
| return "other"; | |||
| } | |||
| public function version($propertyName, $type = self::VERSION_TYPE_STRING) | |||
| { | |||
| if (empty($propertyName)) { | |||
| return false; | |||
| } | |||
| // set the $type to the default if we don't recognize the type | |||
| if ($type !== self::VERSION_TYPE_STRING && $type !== self::VERSION_TYPE_FLOAT) { | |||
| $type = self::VERSION_TYPE_STRING; | |||
| } | |||
| $properties = self::getProperties(); | |||
| // Check if the property exists in the properties array. | |||
| if (true === isset($properties[$propertyName])) { | |||
| // Prepare the pattern to be matched. | |||
| // Make sure we always deal with an array (string is converted). | |||
| $properties[$propertyName] = (array) $properties[$propertyName]; | |||
| foreach ($properties[$propertyName] as $propertyMatchString) { | |||
| if (is_array($propertyMatchString)) { | |||
| $propertyMatchString = implode("|", $propertyMatchString); | |||
| } | |||
| $propertyPattern = str_replace('[VER]', self::VER, $propertyMatchString); | |||
| // Identify and extract the version. | |||
| preg_match(sprintf('#%s#is', $propertyPattern), $this->userAgent, $match); | |||
| if (false === empty($match[1])) { | |||
| $version = ($type === self::VERSION_TYPE_FLOAT ? $this->prepareVersionNo($match[1]) : $match[1]); | |||
| return $version; | |||
| } | |||
| } | |||
| } | |||
| return false; | |||
| } | |||
| /** | |||
| * Merge multiple rules into one array. | |||
| * @param array $all | |||
| * @return array | |||
| */ | |||
| protected static function mergeRules(...$all) | |||
| { | |||
| $merged = []; | |||
| foreach ($all as $rules) { | |||
| foreach ($rules as $key => $value) { | |||
| if (empty($merged[$key])) { | |||
| $merged[$key] = $value; | |||
| } elseif (is_array($merged[$key])) { | |||
| $merged[$key][] = $value; | |||
| } else { | |||
| $merged[$key] .= '|' . $value; | |||
| } | |||
| } | |||
| } | |||
| return $merged; | |||
| } | |||
| /** | |||
| * @inheritdoc | |||
| */ | |||
| public function __call($name, $arguments) | |||
| { | |||
| // Make sure the name starts with 'is', otherwise | |||
| if (strpos($name, 'is') !== 0) { | |||
| throw new BadMethodCallException("No such method exists: $name"); | |||
| } | |||
| $this->setDetectionType(self::DETECTION_TYPE_EXTENDED); | |||
| $key = substr($name, 2); | |||
| return $this->matchUAAgainstKey($key); | |||
| } | |||
| } | |||
| @@ -0,0 +1,185 @@ | |||
| <?php | |||
| if (!defined('DEDEINC')) exit('dedebiz'); | |||
| /* | |||
| * This file is part of Crawler Detect - the web crawler detection library. | |||
| * | |||
| * (c) Mark Beech <m@rkbee.ch> | |||
| * | |||
| * This source file is subject to the MIT license that is bundled | |||
| * with this source code in the file LICENSE. | |||
| */ | |||
| require_once(DEDEINC."/libraries/fixtures/crawlers.php"); | |||
| require_once(DEDEINC."/libraries/fixtures/exclusions.php"); | |||
| require_once(DEDEINC."/libraries/fixtures/headers.php"); | |||
| class CrawlerDetect | |||
| { | |||
| /** | |||
| * The user agent. | |||
| * | |||
| * @var string|null | |||
| */ | |||
| protected $userAgent; | |||
| /** | |||
| * Headers that contain a user agent. | |||
| * | |||
| * @var array | |||
| */ | |||
| protected $httpHeaders = array(); | |||
| /** | |||
| * Store regex matches. | |||
| * | |||
| * @var array | |||
| */ | |||
| protected $matches = array(); | |||
| /** | |||
| * Crawlers object. | |||
| * | |||
| * @var \Jaybizzle\CrawlerDetect\Fixtures\Crawlers | |||
| */ | |||
| protected $crawlers; | |||
| /** | |||
| * Exclusions object. | |||
| * | |||
| * @var \Jaybizzle\CrawlerDetect\Fixtures\Exclusions | |||
| */ | |||
| protected $exclusions; | |||
| /** | |||
| * Headers object. | |||
| * | |||
| * @var \Jaybizzle\CrawlerDetect\Fixtures\Headers | |||
| */ | |||
| protected $uaHttpHeaders; | |||
| /** | |||
| * The compiled regex string. | |||
| * | |||
| * @var string | |||
| */ | |||
| protected $compiledRegex; | |||
| /** | |||
| * The compiled exclusions regex string. | |||
| * | |||
| * @var string | |||
| */ | |||
| protected $compiledExclusions; | |||
| /** | |||
| * Class constructor. | |||
| */ | |||
| public function __construct(array $headers = null, $userAgent = null) | |||
| { | |||
| $this->crawlers = new Crawlers(); | |||
| $this->exclusions = new Exclusions(); | |||
| $this->uaHttpHeaders = new Headers(); | |||
| $this->compiledRegex = $this->compileRegex($this->crawlers->getAll()); | |||
| $this->compiledExclusions = $this->compileRegex($this->exclusions->getAll()); | |||
| $this->setHttpHeaders($headers); | |||
| $this->setUserAgent($userAgent); | |||
| } | |||
| /** | |||
| * Compile the regex patterns into one regex string. | |||
| * | |||
| * @param array | |||
| * | |||
| * @return string | |||
| */ | |||
| public function compileRegex($patterns) | |||
| { | |||
| return '('.implode('|', $patterns).')'; | |||
| } | |||
| /** | |||
| * Set HTTP headers. | |||
| * | |||
| * @param array|null $httpHeaders | |||
| */ | |||
| public function setHttpHeaders($httpHeaders) | |||
| { | |||
| // Use global _SERVER if $httpHeaders aren't defined. | |||
| if (! is_array($httpHeaders) || ! count($httpHeaders)) { | |||
| $httpHeaders = $_SERVER; | |||
| } | |||
| // Clear existing headers. | |||
| $this->httpHeaders = array(); | |||
| // Only save HTTP headers. In PHP land, that means | |||
| // only _SERVER vars that start with HTTP_. | |||
| foreach ($httpHeaders as $key => $value) { | |||
| if (strpos($key, 'HTTP_') === 0) { | |||
| $this->httpHeaders[$key] = $value; | |||
| } | |||
| } | |||
| } | |||
| /** | |||
| * Return user agent headers. | |||
| * | |||
| * @return array | |||
| */ | |||
| public function getUaHttpHeaders() | |||
| { | |||
| return $this->uaHttpHeaders->getAll(); | |||
| } | |||
| /** | |||
| * Set the user agent. | |||
| * | |||
| * @param string|null $userAgent | |||
| */ | |||
| public function setUserAgent($userAgent) | |||
| { | |||
| if (is_null($userAgent)) { | |||
| foreach ($this->getUaHttpHeaders() as $altHeader) { | |||
| if (isset($this->httpHeaders[$altHeader])) { | |||
| $userAgent .= $this->httpHeaders[$altHeader].' '; | |||
| } | |||
| } | |||
| } | |||
| return $this->userAgent = $userAgent; | |||
| } | |||
| /** | |||
| * Check user agent string against the regex. | |||
| * | |||
| * @param string|null $userAgent | |||
| * | |||
| * @return bool | |||
| */ | |||
| public function isCrawler($userAgent = null) | |||
| { | |||
| $agent = trim(preg_replace( | |||
| "/{$this->compiledExclusions}/i", | |||
| '', | |||
| $userAgent ?: $this->userAgent ?: '' | |||
| )); | |||
| if ($agent === '') { | |||
| return false; | |||
| } | |||
| return (bool) preg_match("/{$this->compiledRegex}/i", $agent, $this->matches); | |||
| } | |||
| /** | |||
| * Return the matches. | |||
| * | |||
| * @return string|null | |||
| */ | |||
| public function getMatches() | |||
| { | |||
| return isset($this->matches[0]) ? $this->matches[0] : null; | |||
| } | |||
| } | |||
| @@ -0,0 +1,30 @@ | |||
| <?php | |||
| if (!defined('DEDEINC')) exit('dedebiz'); | |||
| /* | |||
| * This file is part of Crawler Detect - the web crawler detection library. | |||
| * | |||
| * (c) Mark Beech <m@rkbee.ch> | |||
| * | |||
| * This source file is subject to the MIT license that is bundled | |||
| * with this source code in the file LICENSE. | |||
| */ | |||
| abstract class AbstractProvider | |||
| { | |||
| /** | |||
| * The data set. | |||
| * | |||
| * @var array | |||
| */ | |||
| protected $data; | |||
| /** | |||
| * Return the data set. | |||
| * | |||
| * @return array | |||
| */ | |||
| public function getAll() | |||
| { | |||
| return $this->data; | |||
| } | |||
| } | |||
| @@ -0,0 +1,71 @@ | |||
| <?php | |||
| if (!defined('DEDEINC')) exit('dedebiz'); | |||
| /* | |||
| * This file is part of Crawler Detect - the web crawler detection library. | |||
| * | |||
| * (c) Mark Beech <m@rkbee.ch> | |||
| * | |||
| * This source file is subject to the MIT license that is bundled | |||
| * with this source code in the file LICENSE. | |||
| */ | |||
| require_once(DEDEINC."/libraries/fixtures/abstractprovider.php"); | |||
| class Exclusions extends AbstractProvider | |||
| { | |||
| /** | |||
| * List of strings to remove from the user agent before running the crawler regex | |||
| * Over a large list of user agents, this gives us about a 55% speed increase! | |||
| * | |||
| * @var array | |||
| */ | |||
| protected $data = array( | |||
| 'Safari.[\d\.]*', | |||
| 'Firefox.[\d\.]*', | |||
| ' Chrome.[\d\.]*', | |||
| 'Chromium.[\d\.]*', | |||
| 'MSIE.[\d\.]', | |||
| 'Opera\/[\d\.]*', | |||
| 'Mozilla.[\d\.]*', | |||
| 'AppleWebKit.[\d\.]*', | |||
| 'Trident.[\d\.]*', | |||
| 'Windows NT.[\d\.]*', | |||
| 'Android [\d\.]*', | |||
| 'Macintosh.', | |||
| 'Ubuntu', | |||
| 'Linux', | |||
| '[ ]Intel', | |||
| 'Mac OS X [\d_]*', | |||
| '(like )?Gecko(.[\d\.]*)?', | |||
| 'KHTML,', | |||
| 'CriOS.[\d\.]*', | |||
| 'CPU iPhone OS ([0-9_])* like Mac OS X', | |||
| 'CPU OS ([0-9_])* like Mac OS X', | |||
| 'iPod', | |||
| 'compatible', | |||
| 'x86_..', | |||
| 'i686', | |||
| 'x64', | |||
| 'X11', | |||
| 'rv:[\d\.]*', | |||
| 'Version.[\d\.]*', | |||
| 'WOW64', | |||
| 'Win64', | |||
| 'Dalvik.[\d\.]*', | |||
| ' \.NET CLR [\d\.]*', | |||
| 'Presto.[\d\.]*', | |||
| 'Media Center PC', | |||
| 'BlackBerry', | |||
| 'Build', | |||
| 'Opera Mini\/\d{1,2}\.\d{1,2}\.[\d\.]*\/\d{1,2}\.', | |||
| 'Opera', | |||
| ' \.NET[\d\.]*', | |||
| 'cubot', | |||
| '; M bot', | |||
| '; CRONO', | |||
| '; B bot', | |||
| '; IDbot', | |||
| '; ID bot', | |||
| '; POWER BOT', | |||
| 'OCTOPUS-CORE', | |||
| ); | |||
| } | |||
| @@ -0,0 +1,37 @@ | |||
| <?php | |||
| if (!defined('DEDEINC')) exit('dedebiz'); | |||
| /* | |||
| * This file is part of Crawler Detect - the web crawler detection library. | |||
| * | |||
| * (c) Mark Beech <m@rkbee.ch> | |||
| * | |||
| * This source file is subject to the MIT license that is bundled | |||
| * with this source code in the file LICENSE. | |||
| */ | |||
| require_once(DEDEINC."/libraries/fixtures/abstractprovider.php"); | |||
| class Headers extends AbstractProvider | |||
| { | |||
| /** | |||
| * All possible HTTP headers that represent the user agent string. | |||
| * | |||
| * @var array | |||
| */ | |||
| protected $data = array( | |||
| // The default User-Agent string. | |||
| 'HTTP_USER_AGENT', | |||
| // Header can occur on devices using Opera Mini. | |||
| 'HTTP_X_OPERAMINI_PHONE_UA', | |||
| // Vodafone specific header: http://www.seoprinciple.com/mobile-web-community-still-angry-at-vodafone/24/ | |||
| 'HTTP_X_DEVICE_USER_AGENT', | |||
| 'HTTP_X_ORIGINAL_USER_AGENT', | |||
| 'HTTP_X_SKYFIRE_PHONE', | |||
| 'HTTP_X_BOLT_PHONE_UA', | |||
| 'HTTP_DEVICE_STOCK_UA', | |||
| 'HTTP_X_UCBROWSER_DEVICE_UA', | |||
| // Sometimes, bots (especially Google) use a genuine user agent, but fill this header in with their email address | |||
| 'HTTP_FROM', | |||
| 'HTTP_X_SCANNER', // Seen in use by Netsparker | |||
| ); | |||
| } | |||
| @@ -0,0 +1,150 @@ | |||
| <?php | |||
| if (!defined('DEDEINC')) exit('dedebiz'); | |||
| require_once(DEDEINC."/libraries/agent.class.php"); | |||
| /** | |||
| * 流量统计 | |||
| * 一个轻量级流量统计功能 | |||
| * | |||
| * @version $Id: statistics.class.php 1 11:42 2022年03月26日Z tianya $ | |||
| * @package DedeBIZ.Libraries | |||
| * @copyright Copyright (c) 2022, DedeBIZ.COM | |||
| * @license https://www.dedebiz.com/license | |||
| * @link https://www.dedebiz.com | |||
| */ | |||
| class DedeStatistics { | |||
| function __construct() | |||
| { | |||
| } | |||
| // 获取统计JS | |||
| function GetStat() | |||
| { | |||
| global $envs,$cfg_cookie_encode; | |||
| $agent = new Agent(); | |||
| $pm = array(); | |||
| $pm['dduuid'] = GetCookie("DedeStUUID"); | |||
| if (empty($pm['dduuid'])) { | |||
| $pm['dduuid'] = $this->_uniqidReal(); | |||
| PutCookie('DedeStUUID', $pm['dduuid'], 60 * 24 * 365); | |||
| } | |||
| $pm['ssid'] = session_id(); | |||
| if (empty($pm['ssid'])) { | |||
| session_start(); | |||
| $pm['ssid'] = session_id(); | |||
| } | |||
| $url_type = isset($_GET['url_type'])? $_GET['url_type'] : 0; | |||
| $typeid = isset($_GET['typeid'])? $_GET['typeid'] : 0; | |||
| $aid = isset($_GET['aid'])? $_GET['aid'] : 0; | |||
| $value = isset($_GET['value'])? $_GET['value'] : ''; | |||
| $pm['browser'] = $agent->browser(); | |||
| $pm['device'] = $agent->device(); | |||
| $pm['device_type'] = $agent->deviceType(); | |||
| $pm['os'] = $agent->platform(); | |||
| $pm['t'] = time(); | |||
| $pm['created_date'] = MyDate("Ymd",$pm['t']); | |||
| $pm['created_hour'] = MyDate("H",$pm['t']); | |||
| $pm['url_type'] = isset($envs['url_type'])? $envs['url_type'] : $url_type; | |||
| $pm['typeid'] = isset($envs['typeid'])? $envs['typeid'] : $typeid; | |||
| $pm['aid'] = isset($envs['aid'])? $envs['aid'] : $aid; | |||
| $pm['value'] = isset($envs['value'])? $envs['value'] : $value; | |||
| ksort($pm); | |||
| $pm['sign'] = sha1(http_build_query($pm).md5($cfg_cookie_encode)); | |||
| $pm['dopost'] = "stat"; | |||
| $url = $GLOBALS['cfg_cmspath'].'/apps/statistics.php?'.http_build_query($pm); | |||
| return <<<EOT | |||
| (function() { | |||
| let u = '{$url}'; | |||
| fetch(u); | |||
| })(); | |||
| EOT; | |||
| } | |||
| // 统计 | |||
| function Record() | |||
| { | |||
| global $dsql,$cfg_cookie_encode; | |||
| // 进行统计 | |||
| $pm = array('dduuid','ssid','browser','device','device_type','os','t','created_date','created_hour','url_type','typeid','aid','value','sign'); | |||
| $pmvalue = array(); | |||
| foreach ($pm as $v) { | |||
| $pmvalue[$v] = $_GET[$v]; | |||
| } | |||
| ksort($pmvalue); | |||
| $sign = $pmvalue['sign']; | |||
| unset($pmvalue['sign']); | |||
| $cs = sha1(http_build_query($pmvalue).md5($cfg_cookie_encode)); | |||
| if ($sign !== $cs) { | |||
| die("DedeBIZ:check sign failed"); | |||
| } | |||
| $pmvalue['ip'] = GetIP(); | |||
| $kstr = $vstr = array(); | |||
| foreach ($pmvalue as $key => $value) { | |||
| $kstr[] = "`{$key}`"; | |||
| $vstr[] = "'".addslashes($value)."'"; | |||
| } | |||
| $insql = "INSERT INTO `#@__statistics_detail`(".implode(",",$kstr).") VALUES (".implode(",",$vstr).")"; | |||
| return $dsql->ExecuteNoneQuery($insql); | |||
| } | |||
| // 生成uuid | |||
| function _uniqidReal($lenght = 13) { | |||
| if (function_exists("random_bytes")) { | |||
| $bytes = random_bytes(ceil($lenght / 2)); | |||
| } elseif (function_exists("openssl_random_pseudo_bytes")) { | |||
| $bytes = openssl_random_pseudo_bytes(ceil($lenght / 2)); | |||
| } else { | |||
| throw new Exception("no cryptographically secure random function available"); | |||
| } | |||
| return substr(bin2hex($bytes), 0, $lenght); | |||
| } | |||
| // 获取某天的统计信息 | |||
| function GetInfoByDate($d=0) | |||
| { | |||
| global $dsql; | |||
| if ($d == -1) { | |||
| $pv = $dsql->GetOne("SELECT SUM(pv) as total FROM `#@__statistics`"); | |||
| $uv = $dsql->GetOne("SELECT SUM(uv) as total FROM `#@__statistics`"); | |||
| $ip = $dsql->GetOne("SELECT SUM(ip) as total FROM `#@__statistics`"); | |||
| $vv = $dsql->GetOne("SELECT SUM(vv) as total FROM `#@__statistics`"); | |||
| return array( | |||
| "sdate" => $d, | |||
| "pv" => $pv['total'], | |||
| "uv" => $uv['total'], | |||
| "ip" => $ip['total'], | |||
| "vv" => $vv['total'], | |||
| ); | |||
| } | |||
| $today = MyDate("Ymd",time()); | |||
| if ($d==0) { | |||
| $d = $today; | |||
| } | |||
| $d = intval($d); | |||
| // 如果统计数据中存在,则直接查询统计表 | |||
| $info = $dsql->GetOne("SELECT * FROM `#@__statistics` WHERE sdate = $d"); | |||
| if (is_array($info)) { | |||
| return $info; | |||
| } | |||
| $pv = $dsql->GetOne("SELECT COUNT(*) as total FROM `#@__statistics_detail` WHERE created_date = $d"); | |||
| $uv = $dsql->GetOne("SELECT COUNT(DISTINCT dduuid) as total FROM `#@__statistics_detail` WHERE created_date = $d"); | |||
| $ip = $dsql->GetOne("SELECT COUNT(DISTINCT ip) as total FROM `#@__statistics_detail` WHERE created_date = $d"); | |||
| $vv = $dsql->GetOne("SELECT COUNT(DISTINCT ssid) as total FROM `#@__statistics_detail` WHERE created_date = $d"); | |||
| if ($d < intval($today)) { | |||
| $insql = "INSERT INTO `#@__statistics`(`sdate`,`pv`,`uv`,`ip`,`vv`) VALUES ('$d', '{$pv['total']}','{$uv['total']}','{$ip['total']}','{$vv['total']}')"; | |||
| // var_dump($insql); | |||
| return $dsql->ExecuteNoneQuery($insql); | |||
| } | |||
| return array( | |||
| "sdate" => $d, | |||
| "pv" => $pv['total'], | |||
| "uv" => $uv['total'], | |||
| "ip" => $ip['total'], | |||
| "vv" => $vv['total'], | |||
| ); | |||
| } | |||
| } | |||
| @@ -0,0 +1,28 @@ | |||
| <?php | |||
| if (!defined('DEDEINC')) exit('dedebiz'); | |||
| require_once(DEDEINC."/libraries/statistics.class.php"); | |||
| /** | |||
| * 统计标签 | |||
| * | |||
| * @version $Id: statistics.lib.php 1 9:29 2022年3月26日Z tianya $ | |||
| * @package DedeBIZ.Taglib | |||
| * @copyright Copyright (c) 2022, DedeBIZ.COM | |||
| * @license https://www.dedebiz.com/license | |||
| * @link https://www.dedebiz.com | |||
| */ | |||
| function lib_statistics(&$ctag, &$refObj) | |||
| { | |||
| global $envs; | |||
| //属性处理 | |||
| $attlist = ""; | |||
| FillAttsDefault($ctag->CAttribute->Items, $attlist); | |||
| extract($ctag->CAttribute->Items, EXTR_SKIP); | |||
| $pms = array(); | |||
| $pms['url_type'] = isset($envs['url_type'])? $envs['url_type'] : 0; | |||
| $pms['typeid'] = isset($envs['typeid'])? $envs['typeid'] : 0; | |||
| $pms['aid'] = isset($envs['aid'])? $envs['aid'] : 0; | |||
| $pms['value'] = isset($envs['value'])? $envs['value'] : ''; | |||
| $revalue = '<script async src="'.$GLOBALS['cfg_cmspath'].'/apps/statistics.php?'.http_build_query($pms).'"></script>'; | |||
| return $revalue; | |||
| } | |||
| @@ -13,10 +13,9 @@ | |||
| </button> | |||
| </div> | |||
| <!-- /.scroll-top --> | |||
| <script src="{dede:global.cfg_cmsurl/}/static/js/bootstrap.bundle.js"></script> | |||
| <script src="{dede:global.cfg_cmsurl/}/static/js/style.js"></script> | |||
| {dede:statistics/} | |||
| <script> | |||
| //校验是否登录 | |||
| function CheckLogin() { | |||