From 6a66f3db07f8caa30602fd25a02581949b55d0c7 Mon Sep 17 00:00:00 2001 From: flucont Date: Mon, 15 Aug 2022 18:39:40 +0800 Subject: [PATCH] update --- .env => .env.example | 12 +- README.md | 13 +- app/controller/Install.php | 81 ++++++++++ app/lib/Btapi.php | 2 +- app/lib/Plugins.php | 2 +- app/middleware/AuthAdmin.php | 10 +- app/middleware/LoadConfig.php | 10 ++ app/script/convert.sh | 76 +++++++++ app/view/admin/layout.html | 3 +- app/view/admin/set.html | 11 ++ app/view/install/index.html | 268 +++++++++++++++++++++++++++++++ public/win/panel/panel_7.6.0.zip | Bin 12569265 -> 12565219 bytes route/app.php | 2 + 13 files changed, 468 insertions(+), 22 deletions(-) rename .env => .env.example (54%) create mode 100644 app/controller/Install.php create mode 100644 app/script/convert.sh create mode 100644 app/view/install/index.html diff --git a/.env b/.env.example similarity index 54% rename from .env rename to .env.example index f0ccd37..037c165 100644 --- a/.env +++ b/.env.example @@ -5,13 +5,13 @@ DEFAULT_TIMEZONE = Asia/Shanghai [DATABASE] TYPE = mysql -HOSTNAME = localhost -DATABASE = btcloud -USERNAME = btcloud -PASSWORD = 123456 -HOSTPORT = 3306 +HOSTNAME = {dbhost} +DATABASE = {dbname} +USERNAME = {dbuser} +PASSWORD = {dbpwd} +HOSTPORT = {dbport} CHARSET = utf8mb4 -PREFIX = cloud_ +PREFIX = {dbprefix} DEBUG = false [LANG] diff --git a/README.md b/README.md index 7014183..a6ff61b 100644 --- a/README.md +++ b/README.md @@ -28,19 +28,14 @@ - 如果是下载的源码包,需要执行 `composer install --no-dev` 安装依赖,如果是下载的Release包,则不需要 - 设置网站运行目录为`public` - 设置伪静态为`ThinkPHP` -- 导入`install.sql`到数据库 -- 在`.env`里面修改数据库信息,包括数据库地址(HOSTNAME)、数据库名(DATABASE)、用户名(USERNAME)、密码(PASSWORD) -- 访问`/admin`进入网站后台,默认管理员用户名密码:admin/123456 +- 访问网站,会自动跳转到安装页面,根据提示安装完成 ## 使用方法 -- 在`系统基本设置`修改宝塔面板接口设置。你需要一个官方最新脚本安装并绑定账号的宝塔面板,用于获取最新插件列表及插件包。并根据界面提示安装好专用插件。 +- 在`批量替换工具`,执行页面显示的命令,可将bt安装包、更新包和脚本文件里面的`http://www.example.com`批量替换成当前网站的网址。 +- 在`系统基本设置`修改宝塔面板接口设置。你需要准备一个使用官方最新脚本安装并绑定账号的宝塔面板,用于获取最新插件列表及插件包。并根据界面提示安装好专用插件。 - 在`定时任务设置`执行所显示的命令从宝塔官方获取最新的插件列表并批量下载插件包(增量更新)。当然你也可以去插件列表,一个一个点击下载。 -- 在public/install/src和update文件夹里面分别是Linux面板安装包和更新包,解压后源码里面全部的 www.example.com 替换成你自己搭建的云端域名(如果云端用了强制https也需要单独改),然后重新打包。可使用VSCode等支持批量替换的软件。 -- 在public/win/panel/panel_x.x.x.zip是Windows面板的更新包,同样方法替换域名。 -- Linux面板安装脚本public/install/install_6.0.sh和更新脚本update6.sh里面的 www.example.com 替换成你自己搭建的云端域名。 -- Windows面板更新脚本 public/win/install/panel_update.py、public/win/panel/data/setup.py、api.py 里面的 www.example.com 替换成你自己搭建的云端域名。 -- 访问网站`/download`查看使用此第三方云端的一键安装脚本 +- 访问网站`/download`查看使用此第三方云端的一键安装脚本。 ## 其他 diff --git a/app/controller/Install.php b/app/controller/Install.php new file mode 100644 index 0000000..85b82e8 --- /dev/null +++ b/app/controller/Install.php @@ -0,0 +1,81 @@ +getRootPath().'.env')){ + return '当前已经安装成功,如果需要重新安装,请手动删除根目录.env文件'; + } + if(request()->isPost()){ + $mysql_host = input('post.mysql_host', null, 'trim'); + $mysql_port = intval(input('post.mysql_port', '3306')); + $mysql_user = input('post.mysql_user', null, 'trim'); + $mysql_pwd = input('post.mysql_pwd', null, 'trim'); + $mysql_name = input('post.mysql_name', null, 'trim'); + $mysql_prefix = input('post.mysql_prefix', 'cloud_', 'trim'); + $admin_username = input('post.admin_username', null, 'trim'); + $admin_password = input('post.admin_password', null, 'trim'); + + if(!$mysql_host || !$mysql_user || !$mysql_pwd || !$mysql_name || !$admin_username || !$admin_password){ + return json(['code'=>0, 'msg'=>'必填项不能为空']); + } + + $configdata = file_get_contents(app()->getRootPath().'.env.example'); + $configdata = str_replace(['{dbhost}','{dbname}','{dbuser}','{dbpwd}','{dbport}','{dbprefix}'], [$mysql_host, $mysql_name, $mysql_user, $mysql_pwd, $mysql_port, $mysql_prefix], $configdata); + + try{ + $DB=new PDO("mysql:host=".$mysql_host.";dbname=".$mysql_name.";port=".$mysql_port,$mysql_user,$mysql_pwd); + }catch(Exception $e){ + if($e->getCode() == 2002){ + $errorMsg='连接数据库失败:数据库地址填写错误!'; + }elseif($e->getCode() == 1045){ + $errorMsg='连接数据库失败:数据库用户名或密码填写错误!'; + }elseif($e->getCode() == 1049){ + $errorMsg='连接数据库失败:数据库名不存在!'; + }else{ + $errorMsg='连接数据库失败:'.$e->getMessage(); + } + return json(['code'=>0, 'msg'=>$errorMsg]); + } + $DB->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_SILENT); + $DB->exec("set sql_mode = ''"); + $DB->exec("set names utf8"); + + $sqls=file_get_contents(app()->getRootPath().'install.sql'); + $sqls=explode(';', $sqls); + $sqls[]="REPLACE INTO `".$mysql_prefix."config` VALUES ('syskey', '".random(16)."')"; + $success=0;$error=0;$errorMsg=null; + foreach ($sqls as $value) { + $value=trim($value); + if(empty($value))continue; + $value = str_replace('cloud_',$mysql_prefix,$value); + if($DB->exec($value)===false){ + $error++; + $dberror=$DB->errorInfo(); + $errorMsg.=$dberror[2]."\n"; + }else{ + $success++; + } + } + if(empty($errorMsg)){ + if(!file_put_contents(app()->getRootPath().'.env', $configdata)){ + return json(['code'=>0, 'msg'=>'保存失败,请确保网站根目录有写入权限']); + } + Cache::clear(); + return json(['code'=>1, 'msg'=>'安装完成!成功执行SQL语句'.$success.'条']); + }else{ + return json(['code'=>0, 'msg'=>$errorMsg]); + } + } + return view(); + } + +} diff --git a/app/lib/Btapi.php b/app/lib/Btapi.php index 168fdd6..691f493 100644 --- a/app/lib/Btapi.php +++ b/app/lib/Btapi.php @@ -193,7 +193,7 @@ class Btapi return $output; } - private function curl_download($url, $localpath, $timeout = 60) + private function curl_download($url, $localpath, $timeout = 300) { //定义cookie保存位置 $cookie_file=app()->getRuntimePath().md5($this->BT_PANEL).'.cookie'; diff --git a/app/lib/Plugins.php b/app/lib/Plugins.php index 861ef63..ee42e24 100644 --- a/app/lib/Plugins.php +++ b/app/lib/Plugins.php @@ -49,7 +49,7 @@ class Plugins } $data['list'] = $list; if($data['pro']>-1) $data['pro'] = 0; - if($data['ltd']>-1) $data['ltd'] = strtotime('+1 year'); + if($data['ltd']>-1) $data['ltd'] = strtotime('+10 year'); $json_file = get_data_dir($os).'config/plugin_list.json'; if(!file_put_contents($json_file, json_encode($data))){ throw new Exception('保存插件列表失败,文件无写入权限'); diff --git a/app/middleware/AuthAdmin.php b/app/middleware/AuthAdmin.php index 0dabd46..f4ab3cc 100644 --- a/app/middleware/AuthAdmin.php +++ b/app/middleware/AuthAdmin.php @@ -12,10 +12,12 @@ class AuthAdmin $cookie = cookie('admin_token'); if($cookie){ $token=authcode($cookie, 'DECODE', config_get('syskey')); - list($user, $sid, $expiretime) = explode("\t", $token); - $session=md5(config_get('admin_username').config_get('admin_password')); - if($session==$sid && $expiretime>time()) { - $islogin = true; + if($token){ + list($user, $sid, $expiretime) = explode("\t", $token); + $session=md5(config_get('admin_username').config_get('admin_password')); + if($session==$sid && $expiretime>time()) { + $islogin = true; + } } } request()->islogin = $islogin; diff --git a/app/middleware/LoadConfig.php b/app/middleware/LoadConfig.php index 82e520b..37e3712 100644 --- a/app/middleware/LoadConfig.php +++ b/app/middleware/LoadConfig.php @@ -17,6 +17,16 @@ class LoadConfig */ public function handle($request, \Closure $next) { + if (!file_exists(app()->getRootPath().'.env')){ + if(strpos(request()->url(),'/installapp')===false){ + return redirect((string)url('/installapp'))->header([ + 'Cache-Control' => 'no-store, no-cache, must-revalidate', + 'Pragma' => 'no-cache', + ]); + }else{ + return $next($request); + } + } $res = Db::name('config')->cache('configs',0)->column('value','key'); Config::set($res, 'sys'); diff --git a/app/script/convert.sh b/app/script/convert.sh new file mode 100644 index 0000000..9468dc4 --- /dev/null +++ b/app/script/convert.sh @@ -0,0 +1,76 @@ +#!/bin/bash + +Linux_Version="7.9.3" +Windows_Version="7.6.0" + +FILES=( +public/install/src/panel6.zip +public/install/update/LinuxPanel-${Linux_Version}.zip +public/install/install_6.0.sh +public/install/update_panel.sh +public/install/update6.sh +public/win/install/panel_update.py +public/win/panel/panel_${Windows_Version}.zip +public/win/panel/data/api.py +public/win/panel/data/setup.py +) + +DIR=$1 +SITEURL=$2 + +if [ ! -d "$DIR" ]; then + echo "网站目录不存在" + exit 1 +fi +if [ "$SITEURL" = "" ]; then + echo "网站URL不正确" + exit 1 +fi + +function handleFile() +{ + Filename=$1 + if [ "${Filename##*.}" = "zip" ]; then + handleZipFile $Filename + else + handleTextFile $Filename + fi +} + +function handleZipFile() +{ + Filename=$1 + mkdir -p /tmp/package + unzip -o -q $Filename -d /tmp/package + grep -rl --include=\*.py --include=\*.sh --include=index.js 'http://www.example.com' /tmp/package | xargs -I @ sed -i "s|http://www.example.com|${SITEURL}|g" @ + Sprit_SITEURK=${SITEURL//\//\\\\\/} + grep -rl --include=\*.sh 'http:\\\/\\\/www.example.com' /tmp/package | xargs -I @ sed -i "s|http:\\\/\\\/www.example.com|${Sprit_SITEURK}|g" @ + rm -f $Filename + cd /tmp/package && zip -9 -q -r $Filename * && cd - + rm -rf /tmp/package +} + +function handleTextFile() +{ + sed -i "s|http://www.example.com|${SITEURL}|g" $1 +} + + +echo "==========================" +echo "正在处理中..." +echo "==========================" + +for File in ${FILES[@]} +do + Filename="${DIR}${File}" + if [ -f "$Filename" ]; then + handleFile $Filename + echo -e "成功处理文件:\033[32m${Filename}\033[0m" + else + echo -e "文件不存在:\033[33m${Filename}\033[0m" + fi +done + +echo "==========================" +echo "处理完成" +echo "==========================" diff --git a/app/view/admin/layout.html b/app/view/admin/layout.html index 4350043..a01a748 100644 --- a/app/view/admin/layout.html +++ b/app/view/admin/layout.html @@ -3,7 +3,7 @@ - + {block name="title"}标题{/block} @@ -56,6 +56,7 @@ diff --git a/app/view/admin/set.html b/app/view/admin/set.html index 6b22ca6..7c3a351 100644 --- a/app/view/admin/set.html +++ b/app/view/admin/set.html @@ -163,6 +163,17 @@ +{elseif $mod=='tools'} +
+
+

批量替换工具

+
+
+
使用以下命令可以将bt安装包、更新包和脚本文件里面的http://www.example.com批量替换成当前网址{:request()->root(true)},每次更新版本后只需要执行一次即可。
+
cd {:app()->getRootPath()}app/script && chmod +x convert.sh && ./convert.sh {:app()->getRootPath()} {:request()->root(true)}

+
+
+
{/if} + + + \ No newline at end of file diff --git a/public/win/panel/panel_7.6.0.zip b/public/win/panel/panel_7.6.0.zip index c1509f617924165b953420252009f794c90812e2..0f3981ab8dbf7261475847b03dd12d4cc1f974d2 100644 GIT binary patch delta 12230 zcmZvi1z1(t*T&^sx-^HF{FR{1SN9-%Qi2X!Y zvA;M#94HPF2a7|*q2e&nO&q@0eM9BU11H>JBVZ$89B#8|DKW3-g8f z!N$S-VF9o}SP(2276J=}g~7sM5wJ*D6f7Dx9u@gvG%o!Qx>FutZoAEEzT# zmI6zKrNPo+Q(zgeOjs5y8dnmcoi)1X~7M4l9POfUShBf~|(FftA44!q&mo!#2P+!ZyJ+!?wV- z!nVP-!*;-S!b)LfuwAfn*lyS!*k0H^SOtu&*?!mo*g@DK*x||pC#rl4=|+)4moAM_ zm{YgWie{wlr3et#@24;?MT$^xfNaJpTG1yjg@rBrxIo1i zAv02?1PHC7IV7Zv(58qW0C*iff(OlDBp9rQWK0Gatb({TLSl> z5V-fwH^hj$m@?5^DQi6qb4>@3b z+Vu7vCgkH}v>N_`%L~4aG@_UkD4XB?5_lyA^W^^J7sV|V^RJ1uXOmTuhKZ0;5tF4& zYf}|g)GZCr+la%~G*tS=jDux5_LPAY1528pj<5mN92Ru;&?4O_==*O6uB1KLG0cc9G>Oi{Cq!~Luf8iS}))bzZzL?<|0cmab;K@ z8b*|GsA8~qGlwquXxOBb!zKoK6_hj;`~Jdl4|TGciY%=ZOqnc{KElN1OjnE+#{BvJ`1I)e zVw}h(BGS#erV7xfJC8jyDPKfIwl{x~tzV+6dJ*YP-~O*`z%wnFflTK2R6YaxHUk@U z>;sk3obn2gw&f$0Vn#m-kg?HYm7+_DvlQx-J`+u!KKZY#Pv2%D`p&ce%0X)DX!Hz) zJ>`GLh`-H3%Z{&k$Xhw?lP|LsMxkAbQzE>&6G+mDNCqAl_Si$;> z3YycLLR9eRt4h%$*&M7>+4o-*N5fINyu+e7=KwA>VPP5yZZZ!s7d2IKkWjD9;m15|B4=F=>GKtV0v^*yWltq7Mrl(0d`xs>L#}vO zqn?}vDEzC5N>Nr}un;{AZo=dYVNp|dZ9~uPN9obeg-D@h&XsX(q2w=uGQ@%@cJyHp z3eaf9;k+ZC#EE|<#$o7SYaK(-(EvQwOQHC^m36w_;OleM?x}&ZMq1e>#mY|B- zwp<>$6i4;0_8g8b#Rv25Q987XDT!UUa=;Za_5`I{cdq0N zL^nlDG3~*XpM)jz@5v!<8KAT`ha1Z1crI6j2?pLO(5B$tSQHHTrV6#lYIQ%^dw62S*oDg0#KEj(%AWtS#Y+{ROnx~*1t$b2o8 z(y9)gI<$^S6I&@Itu+c?S+tFkb~t((()2axZhC7fS&QnQtwF7C+j8j9!_$CtnqxP{ zmtZ_@&P=wX^Cf67O$itJc{U->wNOUgXYOe-an5L3yH;UAe-w{yO1|sRecjIn$&9Mj zVF14BV_1M0Ij&cXlik%BLnh6~Skcz?hn$>fxk+#Hz>Sh-?scK z8Ix=yqHgu}`laFIjfgt+yEm7NhI;GMGZxjWw^GV?^ERTOO^^f^Zwd?cHY2wY-Uf7m zNqPO1(r=p;J~A4rq&q&|dQ`d@0ZZK)Bulc`0y@vhhURU-f;f6M_&U<8ZJ0Qlt%?CM zQ=bOOp5$8<-ZIkwC24F!_QLQ6vZMTMim@_}R3&|9KHba)vZdfz7{Ijc=*vA_)Z%9S%WzaF_hl<8YP1Rx=Kx_hN%y zw_spTojdsG(v`jFr_`D&Zu{8n<-ozHyN@Bo-p4ZB*@yib;>6`46-Z&-jYD+>9`N43 zad4?r_^J&cn+ip1I)r}k%ppOxq*pFWQyqVI5c7^+>lj{K}&cRG+ zOZyL?wQ&rCJRzvzYEKmh@p^Pu366(QMZZLza_b?4>t=HZk^5*<=flWWo z(&nhbUobt(l}!wS&T(jc4CCHd$6@s`l;n7xL#yLhyHq7CKaOgeT;`q@Cy-#$T@K4m zV57WK!r<4wrqsFyTRLF4AE_P1WR>~(8PG;Zg1{>=0LG*CF;*EdzVfJCCXQae>3k^GMnH8G{UAYr_>U z9v5&>M!fQ)g=*t$>C*+=@lXGuKHvScDf1$x&Fj4~;MGMOQdj?>4r=4{Ddi6YgnVcS z=t7?vUH;rab~N#lB1{%qublI@moPK-#^ih(s}z43>+8~i!>h}fCN*ac6RzN1``nMi zaF20K=-U+xaM*CJ#Qlkei@Z6!_!B9o`*Dc9iY!;7IkZn5XG&kLqT$k1u1vUw*rYrT zPp@HSu21D~?>fF87=Im0-)N&s2@>R6INYunr$sS0km`IXS8m)uswpQqoVha2fC3+4 zD<$2;Ryul-$#!(@Chp9@I~;bs9H&E3w~(R(K7QZE@p9u9x_k4QL9Vd%3%fcLY5AMc z%iD;G7pR=gQt%zz_y-L++`Xd+77jP(VARInkP_}9HnJsG?%&1w+O*;jcn|42*>cEt z@;Bw*;e5D<3cb2e`2$qwe;>&Qxp2639}`kHjDzn3EWz3U1{p%@KrW7Yh>5q3<|*qQ zVw)|G=iu=O)6qGV!`VlQP+@Nl2hYDy@|0;R(4Y$o{PpSKU#R=J$mPC^{k16YF_gjr zuGBq7a)bFCLRa}4P{0$o{gleNCn&XI5qImXg&P}0pF*EvY*G8UyuSwB_}M|e!{nDr zx!+0j<^GJ#+Cd&z^$eTF@(G8;|M_dvfah>KzfvjcwEsCe{PM0rS?V5OMEzeNBkfu47~Lq8T0R}#-*1RdW)*>r*{Yu;nTf1lwn>IMpP_yG5v>s(p>0b3#KAp={g zdlz6x4j?QlKBC*EA34Mdfd*v#Ke%JRa^>Um>|R*=OFzNXhK$h!#(mmR~Gz@*SaUmf=F#juq_#U2RSWQ zlAKY-Kcw{oZ(t53N?-mDoTl6Vq59GwyiEVZ@wjoLG9ddW-hYpmD(Tx#ynKB=prp)t zoV0#Nm9*nR5I%j^qbUF0bVO6KrJZiU`b%>p58-N`24U$NDNtB4lsgmDBp<=mox@W# zDM0Y_;xJy2e1#7_93BYp9QEU1Ha@rsrOJ@8e}A2@qcIQ-KC~>mY^pVXmClk-~)|$2s`u!jn>~ zjMbI=1UjPvb@J4MdvYCD&geqI|O(ZX2$W;ziP0&N#Lk>O7u-)vQ za5!j&jq?0C2bZrQn&jFP$*VtcWlvMM4SsUy+6*vOhtyhP8MihI#S3OL#8y~w#i==V zZk7{=I+svG_B_<5W6e?3&;eX-*8(vehH=Op8>&Y;TOh?}cdoQD#~KbE!Jr+j@ekFZ za&x$IJeZO%?DJ$-d(sU-@`lZNq$QHC8ADSou}p0(FtB!BEXIy!3xte@fru|F}mGug)s4fO3@&@R+!Jk*IZfA3U|W34;*xa zFe7ShjRtC8xw6a}H=I*Fhh{dYDodU2x5lj1nId+R4Pt*YAzZ+ZEUd>|2kfxQXb$xbSc7ZH9Gv7~>f|^T`R2DlzS~(US&#JFLb)rd z6fK(37WF-z+n^M+V;c)UqOcC~+M&Ej#G!g)m>#LON8@S5TzPXSOq+7sB=a zW(UORALdHPX%sPyDYNjK3QKzPEb`PdW#{<@rRWYuncopY*BdMxi3fHCgPLhYLpe%xaUb$Wsp+^bMkTmuyCBK>oQ~JQ9q18&MxGutk(z-x; zb6P1q?IQWhvhOMB{Obr~O6!UMt@}#J|4jrsV^Zg5N-46N6ez3YWK9pdNq(}FR}DUE z3hpkAm2LdkKvs06yX33(ocec@n$e)&(CUR_B>y&LKcl__Bl$Nl9ePOPWOD){Nf8@q zP63Om^l4`gY@(yV^sWbvviA+wCKUTSHhonj6PwWW-=!#_(JT&wiz1C_nG3!wOzeq< z?{{*!wkH}KuH^80FKiu)X0))ElprgN#CQMklN!^7)I85vZ&ly_==|YMlySAk2zHxX% zcEzsx6Hotsk{MYHk2B%3amN+2v271;{pLuVHo5di;Lev^S=V0*lO=>sVx2qk7X1fc z$Rj2;Ncd%8fD|Bmozp;#$z-79Et@w>Nm&CiG^Zs>dOlF{mDw!8k0@+beFsUwvhb-1 zoX!lAd}M?AFkHw2-h z7b>OTp^_$j86tVgx<2?<@|T@%k<8P(4nx4@p_pTfzW++TGOM9V+Br;$lGTSOsjVCC z=E!(*9x0hqu^XnUSP8F(OWLGA9LlwS6&=bOjx+n)THXLL!NSOGD$u4xcdXvMs$Y~> z?zpeFlaG6HUj%IwU&9Z1VzKO6Wtt%6+f>=&K}ZqAzGJRJJCZAWIbce zVd5wx?AVckIXxJK`uBFCwSL$-u9+zsCu+a zXm#XYr7^V{14TVd71NwnFlEHQiVazNNuz}g(W)35+QO8-vALC*?WwCbT3KSPl!^_> ztE-Hu)*BnuJe|wdK2n@;HJ3p%+USD@x_KP*$Kv5WNC|W1rZlFxW8tnV;O>uOF%Z3( z9HM+N7o{5+SkX;iggsS)n;$&-JD4X)aBsNU(VBxPI^;SIVe86y0%ONi4cft!8~-Z! zwBirNe77pbfD)?FbQP0_R{mGkpr!#RspRl4@{#}?N-Hn@qBIFaJs0rlGd5s-N(+UY z)<+fHm<_loePi+k{4B4`ZAch(bIJ;Xd=9_BtK>&v7`klcFG^TAZUghhzbJ`oQw`YA zJ%p*7{wr&%hK{dJ@P8&$Y0*TRFmx}WSsA%T;uarXmP*-GspfPv5(miCf2dOw4zYcE zQpxgYY71Hy1>Xx!cGNT)RP!K}cAZIULRpMH|3mkpaWMLPQTjl76f_>EV^f1P9v;{- z&4{0<569yW>oLDUw)OG^XNM^tyyo zOVXSGI{Oc`$V=C!Tqbo%ZU}EldHLx&^Z}A^A)TD!BufgNi0OPag+VLoJ2PFI?oEVy zMFCUNgpP$gEOU9f9$koo$7umsPr}ZqUBa%GR51xFG%bme60kW-;_+F_F&^{UGg+mK z6Y3klhAa}`88n}HGK5P@*wu=36LDIFtYctFJ9kadqS=Y)$8`@+F!#t5e0XKbghO1J zn1lw~j&XR9gf|p>qYO43Ey+I_cax?AIZZ~ci^+JWJlT#xmh65iG1MFGUM8AJemZJkvIGCAX>QXGJgC zHx(~r-G@?(Y0`LM-$;HRD(Jk3 zI*cz-=NY&jyF+tlpua~?=;I72RA&1=n|urKYPjKRHdPcrDf*sGEoMrI!j^kfI8#cN zJ^P$nG)sz*$?J0|dKSifRFlr)YHV+r*C-+`Z1QBs#IX3NI5!I0j#nX{**I|?+tc#d zDBIVKe#}O9dY%+1mm-9FW9byTY6ei}LX_PujTRP4;j-RC8xE#m_?u`YzI?d6@d@Hq?DS0$TT` z<@3>3q6__G*T05P!~#rVsz04&*RP?}eIXj2Pnbb!xigy5u7%icUs8(}A=oT~q84HP zQ|Hq~#+w?hX5_vYkHZyYQ9~?aN3iR0a)u%m6aMTR?F@wG= z!LnW{B)_GYkDy&7Ek%v7hsdr7%hkSy3X7lzKBD(UxCLCl7mzn$HL@Gcq*B9~c6?$U z6DDQ?QTt_>yZ^1Cxyvw)*zNRb8FHW4O=Fki=y|@I%9bPdxjodl7^OeoM^lOspH)FO z+4XJ(xvaoe6_3%H6_~GzW2Ckc*U%Fb!LDvKbYdk&8COFVt1!TqCn;+c^zYB;_9{$x z&zCfCHS)y0q)n^QukmZrT!ZVb*A%@5wda1AO||SFf7Q>X_9ck)meJf2^ysEeuS;;J zC#cJ5t*N{@g{{Sm<0t&`wb)<%EajBc0jlFVsDHPiymeTB`yJ@TI`sNG{;$A#ux($e zT94b)Xn>shd&-+pzYU0R6w%SbtmN|syD!;Oeqn@L?a zNs+RI9Q0p^w&k0kewa>bn~`}61>?4yLo>Hve52>klP#Fv zv^nIu75?>eXzf-hUih$(OtxVi?iW+$HXIQj*U?|wq!=M!1C81a4&6itw}V5sll=}X z>AdZ7sy-mctJ)6qZdgiRcHoHZR!U=bB5PPF?b#_!6k^KAx)j$9Wi%I8*~?vWvXbPM z=JSTy8}_4H z6BdW%W?7B@N*L~>V+ELoN4{PFnoJ=Zk5Gzi~ z>FpJ)ug(E9U0op!FuGqWZws`{U!SNk#Mj&*VhzJ=(9s$Lzy*GUDp{!m#~9cU=PIPOR)K-OqdEbQBxY?mo>viW_$Q1A2NC8#m)M4L>FY$-cak)3#%{4|^Gq!Eu~2$%d42 z94CX!gsvaQ-SXa_`klbu(>_imC&2l&q*;S$c0NtfHQ>JI=xh!A&hMzxN!+QQz7*5q zlL+W#O&?Ce@wpp$*Wwx7vODdl1rO^^2B)y(+1;zCbYN9$T5$@4s_j89PT|Gy?;cgu eX-JhlQ}OnDTCz5b(TLF)ktZ~o+Peym;Qs@!AW?Gw delta 15630 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\app\middleware\CheckAdmin::class); +Route::any('/installapp', 'install/index'); + Route::miss(function() { return response('404 Not Found')->code(404); });