From 4bd3b836f80cd9a2622e005b09936b4a401af3d8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Simon=20St=C3=BCrz?= Date: Tue, 13 Nov 2018 22:36:43 +0100 Subject: [PATCH] Add network test functionality and add live log viewer for debug server interface --- data/debug-interface/debug-interface.qrc | 11 +- .../favicons/apple-touch-icon-114x114.png | Bin 0 -> 4427 bytes .../favicons/apple-touch-icon-120x120.png | Bin 0 -> 5074 bytes .../favicons/apple-touch-icon-144x144.png | Bin 0 -> 6576 bytes .../favicons/apple-touch-icon-152x152.png | Bin 0 -> 7460 bytes .../favicons/apple-touch-icon-57x57.png | Bin 0 -> 1504 bytes .../favicons/apple-touch-icon-60x60.png | Bin 0 -> 1600 bytes .../favicons/apple-touch-icon-72x72.png | Bin 0 -> 2150 bytes .../favicons/apple-touch-icon-76x76.png | Bin 0 -> 2364 bytes data/debug-interface/favicons/favicon-128.png | Bin 0 -> 2957 bytes .../favicons/favicon-16x16.png | Bin 0 -> 305 bytes .../favicons/favicon-196x196.png | Bin 0 -> 10039 bytes .../favicons/favicon-32x32.png | Bin 0 -> 615 bytes .../favicons/favicon-96x96.png | Bin 0 -> 2906 bytes data/debug-interface/favicons/favicon.ico | Bin 0 -> 34494 bytes data/debug-interface/favicons/favicon.svg | 57 + .../favicons/mstile-144x144.png | Bin 0 -> 6576 bytes .../favicons/mstile-150x150.png | Bin 0 -> 16905 bytes .../favicons/mstile-310x150.png | Bin 0 -> 43775 bytes .../favicons/mstile-310x310.png | Bin 0 -> 65944 bytes .../debug-interface/favicons/mstile-70x70.png | Bin 0 -> 2957 bytes data/debug-interface/script.js | 152 +++ data/debug-interface/styles.css | 201 ++-- libnymea-core/debugserverhandler.cpp | 1026 ++++++++++++----- libnymea-core/debugserverhandler.h | 35 +- libnymea-core/httpreply.cpp | 2 +- libnymea-core/webserver.cpp | 42 +- libnymea-core/webserver.h | 1 + 28 files changed, 1140 insertions(+), 387 deletions(-) create mode 100644 data/debug-interface/favicons/apple-touch-icon-114x114.png create mode 100644 data/debug-interface/favicons/apple-touch-icon-120x120.png create mode 100644 data/debug-interface/favicons/apple-touch-icon-144x144.png create mode 100644 data/debug-interface/favicons/apple-touch-icon-152x152.png create mode 100644 data/debug-interface/favicons/apple-touch-icon-57x57.png create mode 100644 data/debug-interface/favicons/apple-touch-icon-60x60.png create mode 100644 data/debug-interface/favicons/apple-touch-icon-72x72.png create mode 100644 data/debug-interface/favicons/apple-touch-icon-76x76.png create mode 100644 data/debug-interface/favicons/favicon-128.png create mode 100644 data/debug-interface/favicons/favicon-16x16.png create mode 100644 data/debug-interface/favicons/favicon-196x196.png create mode 100644 data/debug-interface/favicons/favicon-32x32.png create mode 100644 data/debug-interface/favicons/favicon-96x96.png create mode 100644 data/debug-interface/favicons/favicon.ico create mode 100644 data/debug-interface/favicons/favicon.svg create mode 100644 data/debug-interface/favicons/mstile-144x144.png create mode 100644 data/debug-interface/favicons/mstile-150x150.png create mode 100644 data/debug-interface/favicons/mstile-310x150.png create mode 100644 data/debug-interface/favicons/mstile-310x310.png create mode 100644 data/debug-interface/favicons/mstile-70x70.png create mode 100644 data/debug-interface/script.js diff --git a/data/debug-interface/debug-interface.qrc b/data/debug-interface/debug-interface.qrc index 822ac02c..89b7a29d 100644 --- a/data/debug-interface/debug-interface.qrc +++ b/data/debug-interface/debug-interface.qrc @@ -1,8 +1,15 @@ - + logo.svg warning.svg + script.js styles.css + favicons/favicon-16x16.png + favicons/favicon-32x32.png + favicons/favicon-96x96.png + favicons/favicon-128.png + favicons/favicon-196x196.png + favicons/favicon.ico + favicons/favicon.svg - diff --git a/data/debug-interface/favicons/apple-touch-icon-114x114.png b/data/debug-interface/favicons/apple-touch-icon-114x114.png new file mode 100644 index 0000000000000000000000000000000000000000..f67b4a2d63d060f1289c3782421f39fd576ae99e GIT binary patch literal 4427 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 literal 0 HcmV?d00001 diff --git a/data/debug-interface/favicons/apple-touch-icon-76x76.png b/data/debug-interface/favicons/apple-touch-icon-76x76.png new file mode 100644 index 0000000000000000000000000000000000000000..4c15f845d308f5b68fb376d33c29a456e5aeb699 GIT binary patch literal 2364 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 i@-$s6{XF?*z5fBQf4MlY?D!!70000{P) ze~47q6~{k)8Me!^ELMVDmaxboiv+QYSXr#JQra|#^p8Xq+olqN6tQWMr4_M3C}~(k zM1qI}5fMpK5fKqeO9$~1>U<;5qaK~`ig=IVEs0Q+fOiTqv>Tt2pC+7>xX{X+!(L!_o7xrx=w^5dG5IKw6(afW;=bHh>(a6OTBb$Nc)qnTVyg)R} z>)|r66Q!C*(d#1U=)=fGI?y-xLW1Ys3LF4_0Q{-?*%)vb6^O*i|A4;%zeU9)!@v&- z9wz<(_#W_=2-nh$6#p?`S@r*)0sjF$s{Y2mBAh=rti^p&cj21YK{OK;@SaDQwi4{7UI`rF`-FEk{bUY35QV9VejfkE9>X0eI7lhZ zk}X9jqo9_##=UL0zN;uZntRsJys=g%MMgd?>;>T3IH?K_jLIBBNHCgv;7Q3(f)u;0+P3ik z-#HuN-t{5HDGbX{fap5yGucU5fn_KW)ap=ocg=lpfE{SOe*;Aqy?mJEzqT;1JsXV=8;3YkS9?htq>eS=Il6fhRiZ?C152o zreVi}hZK4RtqnFshmh6svs7go zPgQeJ2Jq_(K0Au0(-)34WUCXS%6PS1uQoYuU4#44i)KgHE|_V?|8dt(){&NJ`77{? zlzux2o<{fbe3RoAz5)!Rz(0V0SO4z-KL>t8feT1WG=F09BC}{%*N=aeaF54*aF8D` zUh~;%G_@|#r#}nyQNNf}p2ds?-tsx-RgZhnkE)o>oP?h0J!#9v8fkl%pCa@5ZnFb( zz&B8a@6SHRcuiCP3Gh2KXP|`2#s3ccI)Q7;S>)`VM5*7jM`5|37u5{p!5SQ| zUi0Ca&t_01&=?x)TT>sB5mX$Rb|?GEnd-Gppr`!^^(kOWM9j4E_ej69z2sc=I=7+t zzBTa)(Sz#gqOK?!x0s?&+wpCp4=F-cqKICxeoGtZK_S>{q+48iB$kL#A>60^ zA$k>T#9b43IeJeg5mYi&L6#I5!g~_xO*C3C*|t?QkJks4JJ{i0>Xgttf|GcsWbdLN zjoGj&&VUa8s3xHbBt#1l|jIH|*u0z+uh$vEzgWZh`y?M>=C z>;Y~e=Mb8u8@BV!s3H(Kh|l0nS!t8ps9 zC9D&eD~=Ga0#s0z(2^6@6aTcZ+Z13o&rYF4GHVRkB9I)hllT?jHU-+^z32ql)hme9 zZUB{AiW&!~Wfmzx+%tE-h`T71CF49s{QC?|;qH2tTROo4fR?5I67aPc&)JRY2k*pq zPD_IH6TdI8zpX7ufKIUh0RKfXf$zk4&UsWFWXTCV#JeZK$Jo$t?$|_p(ZLxslgN@I z9OB!ptc>;zw&aWf>I*%iNUrzw?bOodkANSe!jY(0A0VeV#FH+z)5CI1FIwIuZ0FBo z*9OWx!-NkIO;f+&vn8hlT^7d3Jv!HqDjd5At^gNPxl&6a1YH}bf>sx^6o@VwZ~5jW z-%95)ElJXi7Jq2g`Gu$luz1so5}a-LZA&5O#y@9Z=Ld8EU1+tCg`IyN1(7TrfP+>L zt4$%>wShYf2dzFfgQA9Zoq!Hy6zw=-u~;k?OWyfEiwASCl^Kig00000NkvXXu0mjf Dx1WtE literal 0 HcmV?d00001 diff --git a/data/debug-interface/favicons/favicon-16x16.png b/data/debug-interface/favicons/favicon-16x16.png new file mode 100644 index 0000000000000000000000000000000000000000..6581a72f58135e6571464d305b96a3669d8b5971 GIT binary patch literal 305 zcmV-10nYx3P)gY&Mx;VvM@bpWDrE-hA82hhNdv>*NE)mNFc7nS+~Xc07i2j_tU00000NkvXXu0mjf Dlh%d> literal 0 HcmV?d00001 diff --git a/data/debug-interface/favicons/favicon-196x196.png b/data/debug-interface/favicons/favicon-196x196.png new file mode 100644 index 0000000000000000000000000000000000000000..d0a4bd55511d8f3cdc5c7e8021b4c5c74798377b GIT binary patch literal 10039 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 QzsS+(01P#&pS}wJUv55r?EnA( literal 0 HcmV?d00001 diff --git a/data/debug-interface/favicons/favicon-32x32.png b/data/debug-interface/favicons/favicon-32x32.png new file mode 100644 index 0000000000000000000000000000000000000000..64bb80f9b3ea03ce930fc5ca24b1961086a0d864 GIT binary patch literal 615 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

w5P0JLh}uzJB|iKlk2qZr$TN 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 + + +image/svg+xml \ No newline at end of file diff --git a/data/debug-interface/favicons/mstile-144x144.png b/data/debug-interface/favicons/mstile-144x144.png new file mode 100644 index 0000000000000000000000000000000000000000..f4ebd8df48b08d61cc327f4411204c4cad505a5f GIT binary patch literal 6576 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 U{yGN)M*si-07*qoM6N<$f(bPQ!~g&Q literal 0 HcmV?d00001 diff --git a/data/debug-interface/favicons/mstile-310x150.png b/data/debug-interface/favicons/mstile-310x150.png new file mode 100644 index 0000000000000000000000000000000000000000..a33560035aa9f22954689f9d248a0fbf51028a58 GIT binary patch literal 43775 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 z zorcJvAj@o8m^4Ja{$TYU*DE2rdo&LGnHyf#Rck*lXQuvQ}J zEVdyp-g64l_KC+Mo}P;k<7ow1jS)OBP{x1QDC)DL;{amR>_UV}8<93F0%3>U^N~LJ zdBj`jA!eKhoQ-^EDC~gSw(MUntRT~aPebJML&zX%Ri%l^`<$N3^$ne_l%DsylxB%u z4zM#3xw1-imd#h1uB0ueo|9eo|P6~v`}HL_ah^btQ_9UZo9th-UyXB9DEu0sOm zRuM(9eRQmM-5MH#@p2JjxO@TsJ@n*Oxb`Gu50RfnRxPz4+~vh?BxrXVvV-^`#=D3I zSlR7)Qal~!#bU$;u%5p1bV{lIvpQ~&NUyKu^p!2w%69L+&1=g{@fPl<>O0l;Tg(OB zAfBONiRk;@6b&;whoJG4=f;>!-AtsY!4=>og}Wt}Hh4knM*uiBOvn6#cPq4Rpi5KOlH z$`+H^vyf5>I2IJ-HL{+=(&svlZBR^l&(gIGwr1$rb6p25bZmpCI%e)+ubDiyeQcR4 zOt<%0$YBL#Y`s4eNz1 zi09;N;9ACCQnv#+-M@DLKaUtKZE9#^VFd};y%_Pj+=+Nz0<7VopSxXLqKyEYbC}k5 zHk~$BY}`spuXtsIG@6z*h&;WN(n;Pxe9bwm&a<>Uov&kOw9fO&wgX~d>~XOQ-+Bgg zBgG!B&SM$CNn?!?m*(GIgCAB_&I^qXhc;N(x~JecOs8jLHL;9ULRR>-TQt&|;UTTg{8#~Lph*45J zD<-|yAuQ~2uaHg~f!Yvy1X1FzVR?n*6M=67UOqa%pYbxffz8U zk3u#y^o187Umm_2>5Bn&S?6`YvypG*v`ywVE_NZ?O`HdOfblc8UXB3IP=IM&1#x}l z4Os1<*V48+f<$_&;I-lH!86oKb#2Os@*Dvv{yk&RXFXWwgKe9bC&tQrkG_u43G}CU*D)?yVd_FW7mj_Qt=q^mZelSgHkKsZw+(7( z!z6uu-*a2xoO=&3=Bd#QX)Rkz(|S?tL$z@<))EbMcq}rneucx&GGPlM1fGZl6u%Jh zmYhW5V8SXS+rMJb=&Ok5=3ju%AVTFfM7ivtd0`sngENuA!d*z*mFLP|LxMZMicB}O zjTPsQu%hueGEnMk0JDO~t@Dv-qYo1Iz^6R<-c*OypLUS#>0GUU?BLv^8KWPYn(@lC z`cs!-4HBy}ZJdhMkDgIyX{U_9m=X2pyXeKZ=n7kF$2Np#l!S9l7n9F6q%|&VgL+d~ zmcF$fbz|9jS>>tA^d447i=pB1=+)U8U;4i8gqqe6SuXqpWIvaUfUStfB?Q1dV{~jq z;$Th?H{M{neO8f8qwWLlK)!|aSwx8KM!YZ$4Sit?^1dBKjF*G>gOfERIQ@yhg)DB% zg3X5gz>Ub%&0hk42D}ycQ{ZjD+eiQ3349pweBF)2$(@E6AGHVr#EVAdf1dF`%MLbU z`oUhe297uQ59fhC>RL*7=`=Q-)v=yeTc;1aXue^31}3I6^}At%baj0^qfFPs8eX0= zBJc{zaM7?2!zyXd(z6X=tuAY9=tlLdLVK>u^Hwrhw^GbnwTjVN&R#mN(PJGICOfq4 zIG!bK-G=)ANyN+WIzwyOu>~_9xTrPFvTh-|uWME60acT~26;+!n^WEo5= zd9BYp13A>e8aIKKXUuq0QJz=Go0joBOEE_POzJ+X%W!Q-b=x@p=Trpg>f$;U~Wdfi*)CR)(*tbD-~D` z4IcI&qwoh1Pv08;63z#Z_w!_TKh$-wVi#A|aS5~H_@@97A??TmrGhV$Fz_lyb8VPFqC zE8=-Atp4_#1D?0U8abM$n4VrS*S)xxiB&;N>S9YDrpuYot#$)Ct59P~-m}DV-VAFH zcPTn;C7CeQU` zmAthuJ)^|?t-TbU$HOZ_Ur$~0%GdR>79NT6J!{bN?0E-byn0I5qwPgdZ$U$ z4`Pfx5BUh%nTV0G4QYd8Ot-Zc3l*-fBEgiwy?ie+VtZsnV;jwt-%y9s7_S=o45Iuz z84x@J=OZ4)=Ix8)F!Fx>0q|Rh*K`$s)?j+ef1KZ*mFF$-wTxQtidE=V5$XJ% zlClPtXLQ(mcEqmJ*$1F`uz5TS*lQ!3PS@SOeA=M#tlw~)MB+ETmyH?cQi2skNn8ee zEAT308tFLVH34ZSFNoP1#o@WEBJk`n@6fi*3)7IpnMnM~N08lxh*tY^F}2T1vC9%ZKW+gHsHq_eQPUNr|~+KXX(ehMYc0q z<0RH*mKV>ewifV^>AIW-T+Z_E=h6pO5aZ%m!1nAUKDMnr-4>fM@pP{>B5hfoPEYB7tB)T|&=&^g|Ey{4y;5EWk>91XYT6`6e^5!! zVmt6}5bulE(N2})bI9EIix9&j)i+{ouYaEd{1Bp$9$JF>wPSgY2apep26*rDPT&WS z&FL1+@3I`f!}Pbu`j*FCbPmX%Xi(;_BN0^JX^KKvy z&2ztp->5wHT0lv9FU>qK?{elze+7y4cq!r~I92D+LtM(~hyu9;3F>_v5?gR45)TxX zR_CxbO7{p7)O$M;K=?Pnr$^WK(w4b4$oqZ9=>JFY`_~%M|Gtc@0z8%b%}v1TfsZkc zQ-k%B_a#_ErXs$ItQbq&6xBR#BRN=ZdTI|Xfn0_ew zL3#J=l3$Oehg=7+^NBWX?B1+&E&W+w=khe|A+iGJIka!}fV9!+h__@fa3K;G^9tab z5%=yHh|moCF{Eg%Axj?*BZ6ul5=i*>dKx}R001BWNklJk^Nde zitG>K880W1KKEGUT|E_X9QeP1cO&nUmT9xf$(TIWF&nY;DTFw|NvAo{(5}sn$Q|+44mtNWuo=e&!n#OKGm-4X081j^C43>sI&s8K>$rukg z{%Yz|`rx}FX7B|(g2cL<$|JcL!Uq_i1UwmW*P6-a%x4 znA;JdbuALu`xV3}+Cej7PBrWt9Un&efhSKML1Ly}%&ECN`Y(VtA)n~bo67Zplx+6O zNGWm~F#2UA7M~s*-a`yV>5K&O~A)8W#ZzX*Ong9L@5+~C> z_;~8zNyt>l7nwGKLHg4X#IXIQb>wRq@F4KZh@l_a#>!~VJ2H!mtnm;8=)t=Fe*`hO zE!~&KyM!hxUrZ0LFkP2g)Oe2uFkTLAm-*^t zO)$OmIQ&jc^W;1r)}7|%^{hE>X|*jQhgxgZOKXjsQg2a>hbp8G?ehrY#=L~KoqZ_= zhypnWnLfH2X~Rnq1LkRnaq|RZWVM2f5>GHKV1w~^HzL5o$KUQil-Lo(80zws+J=pT z?MR>c6yjO&j$0b)vl=VW9`o|fj-|NjMvd$|np z)UF`U`vmYFCS!JT(DFOwnb7r54T5dH)Oj#0Qd^UxXjndVUA$+SL#Z<(cJ0yfx8Sdf zk99CzY0nBPfz7Y2Kx;(B)_JE;V%3*e=r(_eb)2#stw$&2De@j_xV8&G=&Oqpl%>>Xd~hYQ zZ_o|MH*h>zupcp8&tY?Z$LKIpzfxtMyYA_kls?JnoRYFVy>t|bVcL%b>272E4DWK% zm)3Vyy%K2H`?bylTbAa{qh;yT(ALj2)?P9Gr^@c4P(7wJVwLnzlD4a-qokwMlxv~u zouhAG##t~#UZhVU3b0{gVF%)^xr}DCY!-Yw5*G#W_x$$|&&=_4;b?tv2>3JSdac~; zDv!J9oRWB>Au`RoUtQad1n<|B--j2fx>WvHo>HDX=z4qfbA06L>hYw@{t)7xZD?p%EY1U-hpbGqG9a8EK{jUF zZ13!0;NysbFO~fPo(zxuwz5Aab5pWArZensjo=*(*v5F8I9A^rpQ&@NuCaWnx>`?0 zj;=*Yw|Qw}{XR#dR3}c} zg^8v8I5G!Y@=czGhKBiJfCOv5)Lggn>Ti)1DVxdbau8WX7q$tgLCTx%jk-M#b}XGI zGrQ0{fYdQy8}Ky|{%tuqeU-{nlCM^8rs#Tky#Fcssq+|(Qk^(ahn!WHv$Fa?szFMv z!dcU-2Wt2zNqY$RCnN~8p`l^1I2YLy=!!&|1IPwux2+3D>w^PG%-v>!mcNHbN5D4Z zS$Cl|&phivb3N>VBAVVjSg>lm7>*jxO7O&_+;g$~Ax+I3UyN?dQ{Q=J2{4L8iW9gQwVZLuyLBW;(+wFE&k)qiywF zNPA>-=ybaZ=>%FHpC#97G0Q;TYn#-Rn^(`i93Iv#naVS85@|+CydkM{G2^4eZI+sv z@_wgWgE^O84Qkt|OIf8;S~mlKjx0lLfw~P1i^aLf3Zv9&zq^s$S8rbzj^>MlOn#Hd zA~xNSno_Ts&hW}BnOcdJ>(R0wWgQ>^_N8=Ue5S5-(M!2}rPE2__ds3qo?mX-rwfm< zG*fx(M;1XCwp$GkoOHSE^zHWi;kw%%EmE8q*0B=KfjE>3G z8d;f=h2Hk}v3#`~*`;Ln8t@!s?ho^!5u_Vqezsu4hMwVMXgltU>;?mqwK&PRhp&#r(cC`L5@-AAeA>S}M3yFt0bNyKB z9si6d@P~-Y%$&^A=P@Opli#UXBJS~y0Rv!iV81r!JvO@dEnWX)lJi!kg8yOEV@%6!jgWq5e#iLtc#IudcVO}mxvukg>1deYEzbvtOw zQkP+^%h=pvu04iK^R$L+S^ZvQ8RosnM*ttk*xR-dM|%wo%ZvfC!|H>`%0JKbeG+*G z&p~2cHX3dR-ib^XLEI}Ho5r!fw;*kH`sjZ+wlO&~5NKLC8XLW*cnh$+4AuEg;G2-8 z?jVNRt@t|yd*!8ci>*^i-j~qUb&q*1Vmd7KY;?$o)rTp4RifWD&ncZc(N3PHC0t8c zV3^;U`BI}LE9E~|W>+3!`803akgpTJ90@f03S(=x9qnkx?8gbtM@tJI}t;|ld-xS``gN8k5BLSQ-L=sULFE| zBSEJ`57y`e?{`eU&dA6x=HYmO7ZZ!u|*)nXg)OTZTqqolOle?bh1i^?3|<7}Rh^I!vLAOxoDJc--wsKWvY&;xB_?y;}0tyLOz!H*`CW>W_U3xxwLad=rG!<)qyfY z_1hXS-ds~`kCj-^5KPk7d1H-Lqm(sj8sE#8x>iavw`owW&M96}ZJew73gV9a3Nm+n zFA{+E3FKprcaQR(i5N2t4Gm@3itOw10VcnB1LOB~6?w1hM;ezEcQO8SK^N=+ehx8S zx?nppP4&o#mxIaFlPHnrYwCK~eC`ROYYzhd6OoZNZx_ALHBW3qzS5=4rR8Z|pW5mq z&`+hSDL0vCtGWQwhKY8Wc>zo%!8G>V%a;o5@zSQswg_o+0YEY20%LPDHLs42dGA3swYv`Z2gE)5G-MQVB{KSHXlO{|g~(LwL1cfIfbiZO zMppjaLq2X~8E}yCCq`;yF^GIRm)VW9J-~M(OS1P<9xz)X&$Z4tXLJM{MLa!T-Wt82 z)70pQRGB%wQBrpj{N(gUO+V-ofc$8l;BnF36g^@O9+;5Evr5Ta3-G))B^H-w(R!Ql z#4JjirnIcmG$r1Q+)}qvnz3_DdkYe?@>7VRaT*f%c05BXc6}A`!t6sL{cjl^p9Q{v zyvW;;QDs|N-Ow>8aGR^FGSY z%_yt@Yhla(A=6ChM$J{G#8nm)tW~zT3VFtorZqIzV>Dv-ERQ*OhEYw~B?ezOPZ^8e zNGFuF75Ew8TamfhbCJ3Bt%!g;?&Qt!vW5i5g^i~^hInIcM+}$;7z^doiGLxtq2W}- znMh2?{fu{-)mTH~%wEUxf2QMOh=(YA(jX?I)|}%^;Khu0qMa2xkU`ZAl*w<+qbIw= zz<7wr&Tm6J%pmbC9|8Uzf2Y@)Fb1#e8bhFqfs@M<<0~NM;PA?d(NFQ1(v7+gJ^GPF z8_#0hS6*eb_aipHWz)wzE~Unh{jH6ulr@-&p^0syobpJdwqCYrEZ_P(HwT&8G$?it z#7puB@LFVZs~3*`pN|NR-H4YYEHjL?l~?cJRT(0N$}NaM{v;CIdoLo;9!9>IG(bk2 z4GpI<&Sq@rA7xq|oJ5TOR|9)lZtvxX5X0pwk^7#^4)WtnB-r)YJ@K*&Y15A*vdoqr z&QmcVR@Q}U&jen^I52lV@Yl%Hc}f>r)C}&ud@0?O^Ni%ur_QZj^4iqfL@(9Gp011O z>8LK&!MWB=WDSg1C0vWhfo;T8=c)N^%eTM7xeZ*^|Fz+kvrfHoY+A2;dq4Hx(uvjE zYtuEx8_s@Vs!3#W7e4FNB{p4;)(eP@NPtq+=a~F zpG1t9Riw`~Z%o6fh|>_yK$v0)2=CNMWRH>;u-rlL??r-hgS_wtlmS*=Jq~y-{TVI; zMAlu8?*YV617vWP(nXd(uRUVt-o2RI4Zp2o_jHEV5q3r; z#!t$y$myn#eprwur^Bbx>aRoVO6jR1?RBvg%~^7um1xu0l}lM`D}tQIB{kLMO_im# zN%p)qskoaQ-4bt6Dy@AcAk#tHkf?a=@z{dAh+mIPCA|!I65~1C)0li#rJgH&?>MsG z!VSpImw$nHW)6<-ua1tBqdd#*8gFRm15ZRg0dOnwj@WkxWM7llAqLDcdR9R;2BKrggYzlMhur=P^4s2%FC^u_rkt8?DEqWHvyb zr@ZYppH~mh6R!;cs}o~he@zdjb!DvXD^A*!?#k&oZ95FYpK$0(c0ozruJlv+X5qPy z{L6}6NFdz_rmbY}co=bo{zu@lQT}cC9~zql=K`-p_Hp>=sN6?Je0n=)wxb=J<#;pV z`LyqoK7TV3bh>C>z2hN7KE!y>VGr;lJ@fSUz>6yR$l>A#$)A|9fvkQkhXhRueTBJa};=DL_y*v^NNk3dWsJ^0h{T7T!))8?&jUvo??t0^ z0F=wL{m7T4U(pj!hmh5dTCSAJ&se(WF*(?~50QB#GEH9#sFC-zI%ppJl+g0@eyKf> z>ND9o#ijtfmnlWi=F2gV%U7B%m#@qHnoiKwXzH^~a(Rv-Be)BY>7N=57z@sG5Rc4N zz>gy%ryG$kxL%JKH3yme(rroo!|$*i`e4NK$3}GDgcwm50GA^||4QWJXKe$#hK-1; zkv@F8x~2_)Rb<1*i&(x5=~n4J*bV6pA>SM7%Wyd|qUp(%Ql2!#!?NQtBsl(E_&dH1k$(PNET7>rWOkW#4Ds6j39@CwtT7T=R>16X^|^@g68O3c zi4_b1)w9Uyel@CC0k+TgRdjz(wQQ(CYD(iJ$dq2dZH(h` zX7S|ISOy?huE6z8Oqcfx?NA#;H$ zHyAMck>K6~$nK&05iiRA(Q$z3uji(4e3a(^B3M8?L3Np3P#tX*c z5k$W18=WtU{^}zRrmwQB!8-Rg(yNN}{}fXip4F=9c=_hlfU^eL)|Azy+**3IBbXcx zB73S_j?68u*D|@_4Y_o5Ef_Non&V#>PdObxMr7glVJ7F+18v(b!P9fg=zJ$*1LlI! zaXzw&={&@k*~R8v4&Si6xB%JDWH0g6de^_Q|deKhwD*3x+=@@~HhS<-wVb>5dF zqoZq#h{bad`4DvDKIHpEVM;G1ll#^`In)>lvl=)l-5>s!w13z3n937^b5q1(FHA`V zON^ad+1>*xHHb=$uG*DRxiU&0evF>?zXUnHuSY(Pb~)p1tk)abn9(E2AtD^K2WCIw zojEYNcPw!nW&9ncaDZVpv6tm)nq!P<|t0ukcRBMobvg9A$F5goC4dvm(6n-@)Y6+>OYT zU9EhN$&ivZnPuTeDs7*k9$oZP9|p|;7;d!}n67A!$(oKki&dKHIH__<<{E3fLN&|1 z`ZPNFz)@tW<wGfNw&!(6^&jkiPn9;2M_4a0!by0<2Q(8l)Kp7;i_WYA!=Q zQ?g@3^M1tpu>*NegX{`&K=a`7T*A+}Ozxj^6!Es~bJFJI{w%V;#)C3T+EN2)R_}lB z22(Ix2Ijv`loQ%D4D~tn;gwU`X=X8~N{yV_I`-jaEHNN&LZ*zaMn*0h0otf3#Srnt zgblN-QFBO7-L{-hW$G zuh1LNl@#u|opK#9r|470Okavy^AzJ@*0TG2K=Y(EL_UD{X2ey!S(WktsoQ3)U&F@7 z02$>!7kI0=9^Tn~$QA>KS&rrYJE&g)RI0d3WZqLu`3I2cqFmW2;{Ze#zQ)kLmT|nC zM>B_5y}HaY)FM^JygmE2tlo_m>-MwPYFtSg_JQg9o_EK4ur`f%-UkN6+abkMtj@FW zSnATW=~LIe=W_sAVf5~D)*2cb=77DxHxrkKL&Qt!DbPhA?B%3U>XomNjWNA+DU-%U zh=7XuUyNSFE zDOb_ZxgIOjn`cYqnTMsAqUl-WvGd&MU>-cyrZ1_>O~4!I@B2dy4Gr};8(GP+Cvty? z>{n#JZL}zOQ$?k6t2&m!fey@F1-^h7FSB3=@WbZXyODt5lAXYF_iLwQV)?qJ%l(h> zQ+qFkl39*o`Y|i0#G=euZGB)pU0SCaR*{JLUs*IG4GpI__8=c$jNxu1Nc2!5&3a)6 ziwo+%l*zqb?nVY)v*?Mi((nh(_4gnfW;Tqm3^7)~^xUK8dC=1+UE)4UuFXQPB>gNd z%6a6;dAioCjSe9ri?`2EUPD8}Y}k!_k|TyyWXj^E^Boa`bi!*Ml}o2K4{ zOcT{kMd@_AfmbuRQ|?Wp<8UO;yirq+lC*vCz6_3pLHJ`UZ)04bd|IbV#d0w;rDbBf(XlUpM10>evg^4uxAk#&) z-{hGGYPTkU*}T%>{JG}(o#bQmQswR$(bOAZ-h+IZI~DM|*-;X!x}KQgr^K_OnXOf% z%V42F+3Ki(T;S5I=p#UF*8FyQ@EG!?*7vgh+&@eA-Lzd&lzMU1`(NC=-PciJK+nzFA zWz}{hzC{P-?n5@J>pIZdjeJVsIqKR$;4O4FhGM9#_dMz6()PU+x^Fxh;{yIN=a`ow z6%f=%JV-8ZwWh3^bOE96vtT_|Tm_VLa*rQx%I>|upVH!88XDFc!2@tPlW`pSo!yUo z0$|Z2;*`fFwb;OhB*fBNYzMx@T>BJdTRC`TZAGSszKzLxydQ}pI&RXZXqKRMU|ici zrTw8K-m^5GwG^rT;7teS@;@5mqKW7u*4U|lAX{mB-t{5a{51i$wQ)JIJSoJyNL@WS zC1rJK(-c1;Soiml7dW*WWkW;5eDESB4HrF-3ST~7bo@oiaLL6rTK!Qnkll^6i_Y^2 z$_7|oSs}JX#}pj_-iS=e&9cvlMpxxu+djE6YswBZJY6x14zs%3)8WN>*E2}8vEdmp zHos^5#26YI8_JF0MtM$zkBb|D}~2{)n%zNQ*<>-^tYEcWvE#i zC4>4{ecT)2nl)r_etS%nx}tJZGWNmLdRS_LaZ9~2vsj$Dk%(@0%U8;9v}tm#THSGC zbgu{gVDx{{Zs~@GQwh&uY!txsdwLLgFBb_Na%Lsrx* z3IoJ*an1}hN@UV*;7TN5S?Bv8-D2=AN0vWdsjl4x{Bj3ceWOo3H7_g;k0o<(0Lp&h?a^4Se!qI=akV)kZznrs+bzru*Q zjfjC1a1i+@?2$x14_5%MVRGl)Ak*&7@HwwggGCxErDd1u+^&XPXFgIfE<@)UnR_MC z%U&EzU!Id_6mo za-+!Iz>`M5`<8h_WI@0SnUrnsLOj5^RVb)@VT$M~##{UEM>gAhH~H_g^{JF&I%K_d zMxT0O7T!Dap{I(xhi-r8h^}|AY$?I$1IzKfl!k`Qj4PO27OfHD zTo$=3dN&fByET_Ef|Ly0!*o#Yao~@USi2e-{oTMT8GCMy1J@$c-}4M`p0^&^h&sfg za~-@j-!Q$-I#y60F2b&Xzsmv}*HeOdj8Nv?Rzt*9`&MM7(V}wwdeU zJwMK3<6O2QTP5tF|EZ$Offq0iP+mm>Xg`+8XK^*~ACPIMz~ha;UokfNO7~CE_vS5Y zOF|K5(IH*=U#~ETY&qWakd1js6`BeL?YbH%HudC9O~nkU+G(Mh2jWee)jWWbde`z0 zGeG-9DB}?Ddq}XZx6edFL&NOYjs&M#uSp<}Id>5p2jAzi*8igh0 zOkDK5Al?*GtkF^<{#YDM%;@p1$2wR|5NdADF-N1zL-*cz6{5qmb? zJ>4e`1HXdI5jW$dpbj*_5}0K3dDp!>-v2Hh30w9oow+2KtmL|vCT8g6=z2z}z8(8kb#vh<9Z}U<|ZePJx|H++#u28sZ=?qWO}O1Qsg{2F+NJKL%r@P zHM%DL$EJu<#*1aJ#8U11#j2%O>XGPLMi=@}*3MmcsNp?k@Raa#H}G@Filar2{2CfI zBQ8Ze4=EXY9gBPSg2$yscBN#~mB_c6_Nr_50RIDj5UVjjRuDZ0cs-LF_&o^x2C{@a zw`WV~^id5wdbLv~8wGvvoNb%fbbw{VvyQr2mbPN^h{veKqB=-dV`DvdDCOs7;1^l^ ze0xK~X2TvNuyj`<&8Ml~K&>xqNBG;DOIV11jl`q`96-J!RPwRct;mNHf0N0L@rJ<9 zBc9=-1w8aIh%CWIG)mSB*|xE<3n5eOoLEhozO3_7EQ4VbLyEUrz86`~>k!Y&-_l;l zhK4?I3F(dAu4i$E3y5dq@@%R+u0euw&sNuNL%vdy%8c0hZY)DM9I+eHbp=f&UG-OkLZLcu8(@bBwVKcr`L`()owL{|o#H@zqG16@BWJMV1jo zY9)!sK*?&C9BOFx(E#&o#APv@a>2nRd1l2iB-Z5($X+jt90fKsY!+O=q!+^CFcNFF zsP}Cb@bxp&_)a7?MaQLt{Z>*&**0W@xt~O)nDh#ww<80o1Jnm`4!RvLaX4c?Tbt@)AA`Fhm5-Ynk3atD&Kx9Op9LT|0Bo_-@l3k_U2$0qv-#z+U)_wW{#Jz75N*HP3qceqlSj= z*og$c?sV=28TDDj%diM+MfkI^B{5jJ`hCc1qVOf`Rb+?UcM&&)b^$*C{Ci~SbjW)c zFm+*)JGyI;F6ORn?P7*VxL zhEwTsF+`=;OQ(iPW0iE;E-z>>UVayN8*SRCp`j}Vz!Q+^qS#daZ7g|G!bMw43G<3r`qazj{csq;pxPTZB&okFjvVDMfkbV^L)P&fSqlocwEt4Np4D$X0 z#Ax|RWQW}_4SfLd(EJXvS=}PM5M5-ZO+Ty5U2n|Fe-{I7U{7Kea%$8+bHOvv=xUwz z<>e^7SDH7)SFX)wvD9a&R|&QubKrjkdrj= zzZZor{LF=KJKa(e(_*IMPQGPhC#tLDC*uF6fLb>)9OQBn_^zUDVb zg#V8tF)#NOmebJCAaNaG>;Kq0b~j}^!_Es^fftgN2Lr?~c{T82b#Dl~1Na~^?Gxzj z8PWVrWQs_q-;YcU{U$OcU4qy&e{70=UdlP9cL&6IOzFb)G9q$e5+40os@wk-aUj%9bgc{;l?=~7BBeRr%YDYWTF+TndQT#DEeGSVo5O^uR zQE@r4J%WvIdo!}h-T+xO^y`QR=7dRi5(&aRm+9bLjrACG&%={FZ+*31?J}=2CemzW zau?eG@0v%*F0r+75+02l-B>vuQhesh=!3UXbfG&hUObe<3iZj$5Lq7mVPszZL1Y)q zt*J~64W}@6Au%7ZID-dS?2_n!mms@mYhKPl;#$6&Nd>eI_%&n?mRBPi$~_D5zG%5~ z53+s#+Zb=*U%O#k4)fmk#eXeQVqWxZ8!d8`jBWSz^w!LZqsSL-4+Hliqpm9#%27kZ z@*#L!z<;+7kB(Iq>$!X?@X+`rQWnC9?n1 z&D5`$s@()mW8TWWZ_L|URMQ^oqIW_Ek9iGJ9v81NCEk=-m8@rAEdukLW~!xC;_2!W zwFYV~{c*(O@-{@^eGlR~Zt+PC4T4?3S&93r$TZ3^{O=mA7q%nY|KElfFyDhr|JaYM zo`)DLHsJUWvSt5YAj_lo&5_p_Ho~B99#i-+EKB&rqlkSS+MBnEDUsS~o>`S_A9HFJ zUEPZF@*LH={np!ntFgXIc^e{v_Z`SSFGmm;^X^ophK5rFJBfcKI^aR%y;-E;0`Seq zmz`gQ1P$9|+}n|lBWlmk>L}0qkwD}yg{^DXS(PCfgQUnO3}7 z*?7Nem@84NwO*Z4#5^;7c7hVc+%+&)^A)3MpIvFbzR`6a*Xu9GkP+7bWc2k)WOUX7 zcNadyYw-g^(b#!Mkj0DO{OcM)2)oob$)$cr?K?)xxMe@ zx6H3Ozb$MT-tSbN()(TV1jP7HwMnXDrSf^aq}s0rHFQ(`MPEMvd=lxSdw|CQr_Ic1 zL&L_!ok+0iq0za0m!5_g4Ub=c)+X>+ItPHdeQ4o#wgUb8}I4nj)4@yN|p$ zkeX>Eo7Z}TQoO`maYNo+*Wz}?ek9MD~z*=5X&&Mkx_WW)704Aa?hJmPtoo&#nNT^ zC^h9D(?MNyM#(gjmc_9$YGr(^40}Dsm&eNh7+T{(H)2ky56u5qI(t2J-y){)Q~ZVW z9$z)|ZJI9kQ*B`H+v~A*4gWoZ&73UOQP?U>bMg5 zZO?Q1C;YDUF6Gjf=olcrs)$GdDJx9VDDifbpwv5%;;$B6^Oe#otxu|cIT|Gva4jD- zBa~8jeJGXY2=GV9^wEz3|C#xIv!tP6nV=09?|nSTav3hikazWu5kuu3CrycLnstzy zO5>H~De@St5}vx`?Tb#0{LbmmS@mm;?n(9qyXAk(XsPv(q)_AP>cfcWGUwQ^+_($b zZSxp zZbGJTKaXq_ci-sVu@Nsvk#}{yWz#(6;YOuhgP5M32Y;Pt#`bZ+`R$#1Oz3nqb6OrO z9ou+|e8{zB&$Cl5LuXH+=9!iBna~%GBEs|a$mi~V9Jq|>T{;^YHUqW+XC&?)V}6Fq zKID5rpFxb3`xt*_;3#6Kq`W;{NTY8Nf!W&uj|TI~$Ptg^9>ys2Q@dGOb%KDkvz zwU$;*oQD2g8WkR+8N)1f=^L}o5B7y+vFc%V584nB)cX(*%w52@A}f#1qj_K&HWzYJ zMXSjB(8u?RR*@;6>yW)x?m~=}{fuL2YUD^)PkpVt>Kc!-D9l>7n!NL#p;)(e_P!2n zE9gai+uz>(SQ-zdQ$@A+OM-n$==6z28xD&$+EUlM@-}30>gZPB+mM|*+b07WHVbl7 zMKGJ;qNjj@cjY$ZojO9lvZJq<$-dC10kN!x(yV+fT6aAP-MKwOWk`I~+Ly~}UY2)_ zhoz4PT1ux&SxeJlMpy(trOz?AvG)Q03b+QDK5F~EG;DO_JT5SvE~;5=cMy4RZbZB* zH;sNDN@ZGdESt=n2bQ&teeo5gV?8c0uSCjQQ5zFe>hVaeKC(f>v%m{Z_PkChW2>*Z zzY?RaOB#J`R>QF*n7YPO*2OEAE9WrqZp797S>QW>D_M>mMH?ErA{Z{Iccv!J%3lw9b-PhSg9x-LNJTkq7y`jqCI2VcnmVb9}Y6P9#@ zoKj5XFIBpl&r~P1bW=Qf#+qlO&FWpM%^$0Shf?FPCcoyve~n^YBKbkg}Y;-}6Klj|1eNa}E6xy0c=I zQ9>@=QRJH`&qnrt*!L&G95ARTD#z0>=Ep9h`?yq~d`r9`%+(v_4SL#^yc>4d(~ zRnD$w`CZb^lSZGkvYsTXd9sZkBX)p<11E9u7lh9+Ol)$hmqeo z9&>cPw4QO8@|L82r|NC*$9PFSYmdJe|G9eA@DeLOmi{pCe*rH5{u_Q!Vnf3+B1{(r z=yycB*$)D50$u|A9&zO#lj$~X?7dCVipf4J+ha1Mbg-PGQ<~mOWAB&Bw^F3!q5YlX zIhVeRZbXzP;FRYiz3R4iSJsZ?WcL@X2kH80G1@V(w`lY0?7Y(@5Zc@gkt z;2{=29ng+;#EuUDXEO=iw|^Shg8vi14+4AWZ!3UOrPEN4ltGe8yBU$K+m=E?E67U| z{s-b~Cf%C(ZSQMZvGW*0d0x4T#Cq^lT6g=5QqXAz75OwjHD$~TnwMCg)4bTW93rms z2aq7%8%Ed92Tq?4%MA^kaToCC$dqS*?(<)dOn?3%5)bnwB*vu%F?kS^@3Y9ilDvJ( z*JaZoFxj3~Hha%up6xvga`a2e&+-@BIai-+c+(^HzfNoE3=`=r4<1c>EtW1t+vClP zp3c=nr}xUxX=6NkWyRVw<}Qm()x~&^T~AHndFgXjaqPLK%FVTXsx4D>v2+H`wPVQg z>985s-vh4#UQSy+-LPB;D~de48REdE=goU5{gVFHS2+N?fJ>33)87KTg1X&E8ye<;_ahrB9(L}<6lw~w z_iCBsp;fY7=`0(%v_q}F>e5Crqp3@N?|KPO$uwI`!WHMx(+_JZT_Bp8a?mdMfuUu~ zTQfAgdnh{Ixh~(P!^vaom@Cuc+1791(6DumwV9=r;@zVK>9(}bGC-#f9V?UpetkXq zv8lvZ8?8AsWAzR6t#FOi*S2x09vZ=ze+0M}+5Y@aBzX5E5?|1!kQx?+JAt<#{WCzz zdISf-RFT+zlnLlVtkhHUuqb|JVa|- zoJ1vVJMH$dZX`P$Vd-JgXyYd4lJs0+;M0$}&tk5$SUDIvF?X6b4HTp4xnpB)wb*s9 zy)o%L!_X_+x-PwE@1?QRNhzK!y^=h!x~BSry_QQG>z_GZjv*gzycYS4Krmjm&bG~z$^h?ODM^$1ZO@6&Psx^&_cq6uXCT-Co|TQZ?vR&BAx%s-rsNEf z>m_YoDo<VShr!Vxu zdmnUj`AXYlJ)cwRT9`t51M(SxhiRV?Xvchx6Tn}SM@j$hL(X(9XBOGAUUlmWeaf?W z*DJhl=Oc)>W#hIB{XvKI`%$yku92MPquja zz~j5rW8kIJG_1V!WUnXxytG!fXlQ+F>!Z&#&oK{6>e<3HuQ5-Pt($iqL$3W|IwPj5 ziV93!i&G9x=($9scXKz&~CIkIR}mUo+{~ zBI)!rNG!l6T!Tq>7R1-%>+-zmAe%nsZu8uosd8%Qdvw<#>2p&*G1sI`>+$dL;JFEN zt~ZY#66JV-TPgaM_f(x@Z6C{1T4$K7ONy?SE=4~~pPodfjcx_r0elphR@w`kK|@15 z4k4eVcrU)|AM*WPr%CnuQdtsyd-66W7i<7-OeVypPD*&P=VbV|v}0`4ek9B{S(V)b!M!7CGx(cuRZ!eOOdmbgJF{LM(78T+eL2{%Y41jmDk#Q zI{ij!pY_5rw#filadb8k|ME@9rv$EABvTC=4tE1@M80aiEU5KdcHKF3v*?K!YU;44 z`qt_mYY%vIQe{NbmIe=6Yt!D-9tCZEc@~@XKIA++rMz`P*Ss;SxC?UDaI8&iCrY(r z4zaTI{n)5vR(K2p{^0xJ(8yYb!zd7vzJEEs(b%hkrplch`}A zUm-tYwjKd!JEh|M|r?>FDaUQK$dATx6Mgv|umOSf{G$s9Kh!`+;0rwz=%XP?Vq;E!c zwdh*ToyIMJ^(|GS-OjgADd`h;YWRv&X@|GLPdpxB^@j1FV+Nrwe z{H3tG+xkc#m?E3)ptj%5xUdNo3+ zq?}S-y#5(WvkE*2900B#9ajR+82!H(*(0W*A>bI(A6KmD&$&TGiD6S(Zce7Ug()O|RHN2OW-4{yg`{;kYbFK~08LI1EKx6o=-Abt6+BK+M zTQ<;XsLnkaTJfZ&sw^+IypkZaVdCBz(=IwMU5vh$PAk+HpSqs0GQ$1vU}JR+?WD_% zJ#YKmV)sgdx-6|!8+z$u&oA(u;!n59FhM&P6qaiT`>aZM5B*{l@xpu>_#Co~`T^i8 z$Q06J={C}7*j%_1_y=U$fAHU{n5>P-7A^OzOtO7;=v?!HLD!gmr!2oI`C)mqIwmH^ zW4y#%jt-D-1B%Yk!vv;rM%>xQJ3-`O&1hdDeOo+X8oq_=km;g zQW~WeeAhB_?bAmYv3t4m9KF8zD&c2dWv9}vXFHWbm$w_Z9JmH}HgF+u0qw(%r!w9P z{5;~F>kIRcf3x137i#1{Fg{B3-Lj*E|E_f_(e=HzTWvs~wd}RG1SUtpI=x0LFvqiW zJ?mIsxA#kF*wIF;oD@=gubKZj8oBcn9cz*1+B;mUsq-v+*|JJTH6=(rYs+iQdzc#` z*7V65SY85j`Nx4T03QQBfOup;;?h=t?TkHW4W|Zf0{#k_E~@E+vHs>M?U<)GhL}7L z_hR|2+)82AcP=NZJ)Vb5%YmHi%E|LS5c3%2o>5NM#qyUvf3IzzFb~< zufxDJ4bLF79o~AYQsv;J_l$^G`{nvh${@A8YJ*zy64H5TY(4CAw|wO4Vatu()BK!7 zri^Yvf_OhZy0%C0wuNTIoC^31@K(l~8I}ls+uwA$*p!hq=wmX(lesZNASPq194(PQ zrPENJjn9_ruvmw{^F?i3}8yv#4&VcED71N)Z zH=O%X=2F)O&Nc5mN2j*@zSGy{>snqauSctt{veZfmU<58pMDp9O7i6RoHcz7YMy86 zx_56E@LJ%{f%}mU@U_niY~JG}@IRREdtQ@oUhnNZ-o;wEIx7$Js7npKdDTrn$9a@d z{G4LTq4n?7oS?RbhfI4yV(Ci$W6Jj`;L*2fhfL?SWq8+WXr%6?;ML96#omv#Q!K5e znVYlq%D4ADUc7X+e)hb?uuZjv$4{;w)V7;vk+(;qo`@9|N>r!k1)yIK{fSZB$0PjY=D107m zPneC4yO1F58#?6G?^W(SDeZUqo$V7j8QE8v;r+HUsFa@)qL0-lHjXV$jTuY=U(ncP=oNmzcO7*Kf z_w-k;uce+_Dm|tgfI+wsL&{hwftNNkTq%uNQ95$&Qom(IZJlfKbuDjMQOo}Vido2B7nql_3Y9uF34&hHe>lr@^m zo1#;CFI8sg!}n+xx#O+C|`v6m9yskZUT zPxVWWpAz?~$IpKT&SLy*0Um=GESDj>=w1YTE#f^nfqZZ;^p#Y7bU8!h`$(ThJ}+gz%48M6Ob90Cvor=5v#wg z(-Ocb03U^HA^+Eq*_<?QIS?y5A61iPM29)tF+FdZADqO~HO0{lvy}Hhy_8x-%9)vua8mimTG46ObfH$J<%h9r(b0IGI+u~!4)16{vahc1fz|)L6}RwU9Wcr zo6x^1+%869yqHdQ;geTii_hd$@x8WTb!GJg z;id7ax>!19cZM73)?3#Kf3JNlWHe0Q-gbq9XLbH(kT-|s3d~nQ-b#8CfY(C?!uuef z1Ymy8>bSq6c@Jb`yjvlk6F7qT;BElF0pKr@$H0mo1Aaf$ao6J7eqv=Y-;aDAMu({1 zvY6xbzbqDb{WYuKm>3nESK6vt=ZGfqgB}}A5sx$5_tZ56HoX&-Rd`JSo0c~fPiDJ| z4R)<=+tjBb`$O2=EXHZbW_0fc@NXgOSStEzzdZp-gnkf`{A@z+OYwL&fHyepF*OY7 zBfHkmcLg?Sm#JlC{H7ZJ*#8pmXy;s=*|cAs^|W%G{dk!aI&msG0X4elj=L9{{Hp%m zHEY)%+OfDpXou+1qmR9VoJtoBjAo48#>i%JzZ$>`Ag>_L4aXt-v^*QYOCg^Ccs^uf zx(A4E4Yc2$g?ta`P5^%b`3BOnAg@s$!E|s3WdD|XSO4v7$r%5Q;%SxloPBmI?Nl&# z{2MDT+g86O_LRi;-pO}3L{qxXWVr%!af z`t|1_)5l(-Wc{eoehQKRe0p{L8qA->9E0ou^Be##hRnP?d!@^%6;4#weaM?ecR|+Z zoLtdA9S8M1f^qPx0R8|ns|6hPvuIkq(r4{sdyNytwcbPPn#GXlMz{J%Bg3uOOw*%- z7FdtJkv^<$6?u9Bp=$f8EgK$-wb4zc%@aJnRedzCLwIcGT<;v_oMr3H;kDy0ahO-T z*6^83PY+G&(J(p?TV!xI309+J>Lg~K;W zS%1@mmKUe=O{nF$NO(v6JfZ>oK3da=yj6b*?_6&X?6XK_A~p>ge) zXOlY{FSGjEdU!gp1ZoK!Z26x7yMtVkYgSNYu!-(YBidf@5-l%#^kA$G9uKbrW?-Ga zia(|v8E;@c5vl6q;ac9&otEb}kskI=v!b)dC$p`0{VB-fnhyi`03><&1Y`!}!If^; zVf-^@5B4AngkK3sUT%UUHIG2n#bo~VAVl|jS9CW(W?znA7V3ryY98oo ztv|6FpNK93b`#J;ulZzseac5$5nWF#t3CqniOE$x#>Dw-+_lNw5Qy}%Pj%MX)_YW> zGb%3wYuBTXZP`J9O-n+_)CXJH&LEo3XGxNsX7e6VFh0>>TzOQ(?mE0*R=+3_ur_AX zie5b!@8~?5?$i#clPS*+Dz>yb+n{WxS#6zcdotep;J(M~#mek7sn_W|TUuUE0=OT* zUqIgA`5LEuvs?|C(b&U0@GQvMms?kIPC;e>+U$$2kGAQPkXfU^l?e!%de{?@LY0dNoGk-@tlk7dq79?>jt@SUQmVF6jR`(=VXJJ@h0x9!ifz>05 zA#7ZV;;Sd8r=M5t8O7L0Cc|g-soF=6ZP8co7vsU%I=1k zeAY%DkBGOmrFYHVfqA;v`bPHGJS{Gx0V&HCATl1Fe=~oG^zN~_4o3 zS9}lP{lUiPD8A`f%wnwVn;I&8yxOm#x-)$%dPcD}im7&d%-RP9ewFx#1V7U~lg;*V ztN3LFH}Xs7XB4~(3-!xzT!sdxf;SaRDQhe*OW*r{h>WrPHVJe4M#ejnU!fn$yTadt zn*e+pWIe=ZA?s1*+J*NF9unGM)X`{;_3v1s7 zS=2k{!1^$NA4mQ30Sm~&;vbt?uZ!jQ1;`h=w*kA{FD~?$a|AQN0(k;raXgxZbIsCv z{DE~DFy+y;h?e149c&#UeJ$^5V#Dm1;WE2swqY_nyLh-&-K)uI0@bs5WpKDYe78SqBhoe#{t|7;JY9@^3FB5o`byc@|BRJ$@5Qr9EW^+=g}GU zx)_e{h0LV&#J}D+5|#Dztsy=i@$adtm0_V8pQ__P1eG|I=|7b%yj!ZCnGTum-ZjfVTBw%Eh-jEivbM9=y+wguTLA0&RTio-+K6w( z_CQ|8s4Q#8cK&a0@b=9Y0r+}I^77IZ&I6Eb_N~s$2JQC@4tBQvJpg}>gU#Wl+Ld>2 z#q)Lmx2|M83`uCL?>8OKuJAsys_Tt7978U3_(A;W|^K0jn~6->EL)}Sv@`ZRmkeuV2lhV zQ`=^Nc<+*kzDHh#uHj_uG!&-f^#cH&X3CC1w%)%5vK{}60emSWdD(}|Y}gIqA~+3s ztaBISvjTUn=${FB&3Pkv*nU}MWyxhkUenDCU`^q zZz`Y7V(Cy>mL`kMkuDzZOs{MV$n^29d*ef|%@~~rL*rl821EU5l6a{TmuRY{30$gc zY!3{ZD6n_?y>B>VQ*fTcS!ZO)ik)`!rmDOTKC+KRG8?h!S?d5+-zX`HrqP%K=;YFy zvg?_0WDak2()G4=s7&W(b++f04h}ABH#Yt3@$l^LOb3B;JK?~30b%E7`R{Tt@QrX3g_k( z-5xGocnH9Mz`-XTtiALB#6D$xb75#SWWMg*V0v^c{xKZZXITu$9&bc4SnP=E$@p2l z*x07|MZ0fDbz(8g#z?OnDzQ8p3nJg~cFAWtcx{l`B)a+jJibm`bYf!vTSmI^nz8kD z-Kp%3wqDj|lOkJ=fKLC~`q;YIdU^w*#j`qEUfSsxt>)2wbs}dwg~hSDc}bl2@jv^& z1+mE1EWz+>s_VeydF=~z-TrFXUOO|ry>_#QwmIPMV$AwNq?7e64_^nXe~tRA$2E|T zA-)>Gt&o|DYaxp|pIH5R{;qXB4M|`=2-%JI@zwR4abS}nuz-AV`gxF>qx&G=U~2O1 z(Pm!S*QK93LiU9Ye*k$b*uKuKV@r#xY=_#&x1g?7;u4G79v$;>4`1_*`m7g^7;iQ< z**Y-XC`Q^imc>9O*8-zq?FsOhul0{&V5GN)+jz6M=jreHf~`-F?;yZE6ql=yiZmlT zv%#_>8{}D{5z$&%HZx<6;mty1p!M>yJc@5vYE7XI-zk+;!s0S_s@B+x|$S;G;$h29T z)5sq+V5P??03U~Z6X~;%g}YZk5~MK+%uSG4p(`M3bsjL+wOvj@l9wlN@PWrm4fX;2 z1c3M9V9gJ3;6p8W$>LL^@%n8vLuh9gG!DCSuJ%!V$IkfLI3M-#C`LqML^d1I!1ig2 z7wK2QwK15@YMPo{(o{_GH=9nIVJb=q& zQ;jS$V*{c${m5i9|mbhe!6q8 zsZr)LjK6hu&u^G6kx#ViUNB?rVP#mJ(M%%?D*qDeYh0?ZfUFVu3P=)jGi2?`J`Q%# z^`>HVKRylFm*oz~tj*PsS)eO0Jb}3uGCOn)Wc&X|;ZLWZgd{jmK;BZicA(4)70v

zlKWA^s zYChJkHtu@5>2ZtIm&I)R9XDXz_Exsm%i=e=%nz6?SseG;6zoP>(MKtsmdM;bJ}tUXuB{uL+mnCU-nkf znB!ppzXExs`eqz_&!|V=7Xo-I6oMmKM)nY+HTjUToWy3<4rYdcqEKxH_rlX|=&gJ*+~ zC$Ext_0mj%KV%^7vDXlqihpD>qISykvGfe5!Xu*3@T0bg^vLS^3C#0K@Ht2V^BTyO z`)y!kdU>{cH6-b{Z={ZAAY0kDZyZJa{AS2&!QOhEi|sfG;O$t4p7<2S*XqDkiA9;8 zS7Mj#PeWt9Ew|UI@uWwtg{o~U@_J&R{h!5FPbUwm`q;8cT(8Kh_*Dri3TMo#&X8T( zHe?REOE8yyyI$`MHlcr2#-C#TLHgGKd@btV7t(MgWPg@-O`yjw;P9sn7%U)();njm z$*vp^0C-(sk4?fZ^^2+Kj^Gl6>@GJd%W#eyaXQ$PEqjyGvHa%bwJZL22j zOda}#{~{AWMT_wDyznU^+iJ#ERDC=is|bu>a;p(-W43ipXnRX+UsNF z*fxU0)BbvVdvuQ$v@t)hw$-?8(N%9dc)YX4*=&Jx?|L&-V8Ew?H^53B2^A^X4F0eNfb6$5nMgKYJG9I}thV_3IMgENpV z@V^d{#O&eXgNFe84;;*90e(D)`biW&SiJONLQgy!+GjJ}vbsin3I;cd35;hHkE6Jp z;Z}H8Vn`*ylkBE+PPxGDn4st7lzKbRB^maEt9wFuqmDAoMjloJE9rtH<`?# zut~p)Wc@eDY{(RM@Rj2{WC8D=Le`Red1pN?2XHHZZ-p%09Wou+~19Ls% z-*oZtZTss?UE@b}wYn}*vk|)!V6v><)=pJ?W~b=x>uVvi7n^!qum?#9o(Xw-=yu4X zo4X-z^LYKLwc&DwcQ@qYjVB>{%3O^DzscZfE1Jh}umPU6*B&Iv`V@fcAxX|PLn^$Z za2CJ^0Q~3GdE{eu#@qAzEH-PfF+lT=;$IYZEwH$p#U0Bh>)Y%V>gr5_wuLvYc=T33 zJNDUF1@qsIu{|*#1$?b%j}7d&lC?V=J`w+(xP8ce$8b0yVZWA0E5LTn)xWxf=>bN| z+#@(vC+5WVdZiv7jdlbLOed>L#5a?xd03w9m)X!B8mGb&gfElhwXMhBb}Ean|64rW z*|YjGei6Qh%jmQ|L+rxp9i2CxuLbaBnC`31Raih0i047Rh4doGBb-k{29dQ&cmMz( z07*naRMKc?<>d`5pNGHalxsRWwnus}IgQ5hvixnrlIhKMi*HcgIhSSBtl~DaWC@SQhk=*D zM>In~^JAH!trrM>2HxEclkMr|L55S|JB6KX2aW7z%c9^~weggY`S2KE^?5ZUd5OMP zG$$+|NyisMW;LDx*~IQ4tna|f^#2@ykKkZGn(HBJQY!GQl>xRXN!IN9A<4^A4&H;1 zH7_s3#q&YNj{^8903UO%XUPDt-X1;v+8bkaAC3Cu*goqGoF3j3GJC*_sXg*-n^pC% zjyKsZ;EdN0dq!=<60D4OD$^z|(X?S>$U2G6rhvnP5Su2;c1HB*qv|I1AwY0RAiFQCrsUhxDCnil5O| z{n&e)q>T`gY4=1dN&v(+)Gw^!zkp*{Mr`nSHU zp`y>{`P#%qPti26g1s&68T|sBU&FNyzElTH8Kc!W+Ig3z+-~p8c-jtQaT>kV*V5QJ zHyvyO!FVvetv)OX0-HJ)d8%g-jQ zUVW?%x_z|IegS}Q!0>JVr-myaZymiH^4jzn$Xb*qvEGlY-`xk<-v53`@^U@$?=T&Q zBuZC6KKl4D)_oa}!TteA((+<#Z-#0L_$=fR(eL1}Em=RY0}AVpb^vE_(Ti(QzmDQS z7H{m08S@>FCW_ficbMxDjg7-Bu3B1KpXzuO>0|31J!WEKrB`RK-c}A9&pf_NZ*50U zKdTo@e3)$O&!6Yj7Ux>SusfY4DYID?%jQA&EzNIqcMMZ*9j{%}m9_@acezVLt7S#m zuFhncovd!G5wp7^+dwS))b(L@iWc5#oo!HJ^|kE-!<%(JYe#RU%F59??qQvOc1OtW zG?wH#vjMBGcPE(X(|BqVS?=(0ALQ%BufoB$ z{S2%fZUXR6A&-zMuTB3oWM7-;5!00bzUu<8nRlFnyaIm%u^F?Wca7nWi6>*_XENuE z$7AG9acxfAq5d&;JgM;Nwe4Kva|tSgZZud&I8(w{=czW<7#NyRRCyl(hh4JG)sTUG z+XHHLoQLe1``z$A+{oZc$d{}C0{Qoj&O!Ee|yC=KyW=$$(m0#9S_V9GFI8hmsVQDfRJ=Z+_dwECtM)qO9 z)&@QLS9niR--_*`I{3wN4qotR1F?A-uf~ zFf~+oZ_;mcoqrekfWAw|ImiOj??k@%w$*U~dCc_P$alhhbcGkS#R(CIhk&;Ts-3fIV`WA#gtyjno4PH)-&B}OzOM7%h3rvs zp=_?!l90a*S)=n|NV4JWAJN+QEM(u34+3~TWZ^E0MVA41C4gUtywSwoXnbnL@98+0 z!Ps^9V*vjXz~3PEvnBEvqG4z}X>=9(u`#Rlv7x-8I5B7J7z$Iw_zHM3bkaOEu)47^ zD1vUiynS4>12-qr&IYWnl5SZOdy51HhpkHXR)H^6ImmT5xZX8=4ui*5PG>8)qZQ;# zhUMX{#I|*buCY4lcC#z#v(?|34I{f`be-11^|XGax}(IMbrb&emewKE=L z?a$hXp6EuO0&uP46*G7IxL$ZN~mcWhri3rTW53Yj^% z8M5b#hP@Tv4?;GkdlKvRI}dqObOnIdO`ueO zWxO-HMVWak1F^~AtQLO8T-B>;Z>Z~8=FjZT@R_eh`T&R9ExY@x>ScL(ezb%L0%8O#qhlvlF+;#k_=fs`;hfE_d;e} zc6mqL--FDy+yy`8c`*d2_c0a^vlx~2YfHoY-m6D8YvJ`_ukIEn>yKVc_WC>=T04v4 z*~iA9C~j8bnm%-WqkVd^n8)nQbkP0Gfy;?vrZmgrjy6pvvbrgdLZ=LEz`9JH`B{&FYWY=*0zi7 z#E~CnzN&wtyF$wkPT3f}Jl(7;0Jssdd+sg|ycM_}vN7DVA+rki;qWH|*zq~YVBV6K z=i(qp1CkJZ8nQO#F&y@_#Y)a&klCKs8`@ogvyeBc{twm{6T|%X21C6WsI?~x_$>ZK zgGMyt0z;z*wrG|VSdRf3&x>JJKP}4++SYcgFS5iWiUZ76?A+4XnSNU@YcDTG!6|1p z()Q5_4r@=VyVcvqY%iYmj?b*_S}w!4GMB*mM;2L@>w!1(Vx86Uvss^YW}6sPb@0Hu z-cwgiqj?UsSC1avorl-?Dm1-1R6+Yd){eHU*9IBrS-0N050z&-V|1s-u3Z7(A3(Og zztG_-$jr+ZKxS1Qgsel+V14Cr$jr+FI7nVvj5-eBnULLPKLeRzX`t=+NdRwz%v$YQ z^73H-KMQ&6mHC_?$+ zz-(Fxq|7r+gcnU4GF@4nneJL|M(0hHd5h3kL)tqadtLLl^=pC1o9<&a^0u0e>f@CI zaeX5jYw-Lil5OucnysR#%4k|L)6WJ$>nm)FZha>NbNxJkH)H)#$%P8XATuSmL+W`C zBzdt@&)RM$Asg|16q2~y0(rX#kTo#(K{juD2;7Grfy`LF3cL4q)-M2f7ex0cpj%(D zaUtrVQ}eNY>czEQd3JrF*Y|C|VfFUpM={RU*Tz^qb7RK_tA|(bN?c=j4YVE= zzEOR$IO*B4)tSXOHvZVL#@a6%V_CaIzQtm72^Q*ifjVIYudGBu6Y&`$qpCwM?}c-| zY1ot=J^nIp96-}dja4ML)ChX1|V`JjhP=4EtcMCA%}I=ws=$zgF%NZM{AIT8|1Yj6RY6nr;uW#^qMjHYdA~;0j36@)ZEy zi-Y}Myu0Lm$jroVL-umH1!9vMAW6VSAdjC|8$AMfMD=3qPNMKT0Dc)VV>E@2d40w6 zM~lz;ZPXXN>rt$?bpd!k?A67}>7nub&C>Pgxr+{ zrtCbjrLBwQ=|c66y!X!C;&?Q3m(PLI3sdnNnz@c`yQ!d8k8Q%-`u!MWjmM^D0=9A7 z4dC^Vq@v=7Cjk5kWDU#`vc@IbQTIiV?;>rxuI+de{5@uNIks$y_on*&+;Yb7@1fmf zyk>mn;9ce!?VP(L=PVnv*-(}d+3Oy@momBi( z$|e;UqJJ-buZ&kfW*DyRlyf1$wUB}QaR47*{Wf5>ItzJ)_!=C%t#lHy4(47*#)B)| z+aQV0HsOx}yd5&z!e9=cAHy^A*(vn3GO9es#+9& zq5dz;|2EadrV=d=jiditJ(l2lu>sVZ@?v#~>d1`8rmyTCF-wB)P3M)v8wR(H@%lJoAv1}TY(Rm4J^gqjmK%o7pb2!Z&gzG_mHn$pGEA;V|^{_ zSC%&%nx6g`^}~q9iz&9gRtGP(SNbi}E$fffwyMUQC|-GEPc;U5W7-hCqa-35*Lr-j z;`dPT9TC5ZoUyu8VJbC8=RD5`985-UQ`AYQi5;-1* zEZTidVwYyO8v(op@)+oykl85@t_JYako7d%s^4cI-(xzS)GdQ;_lpRkF(50SOOL5} z4B_1yOD+@}Z5?_a71=u=i)S-0mL;{aEUU|)&3Z6B7N$JQ(!5N!s-MlIJw9XV8^K(B zJ;-d+YyUC$z0m6my?$EJJ^H}hbpXB&!1Fp}UdV7I@A0e+)8{v4pI9`3z)Mh2cH|SvT|&Z2oTZaRC1U zz-N)il!~7*f2;ChF^7FLch8iu{?GcH<>B?G=utq_pCTG48mn_e=e_ls#UhVi6o;ZX z<(09UasAtC^GM%_CTlmZj!aKBz5{iC&^%p;rn=a*%G8)AbemIHOm};IDBq|&y1ppj z^~mgn%qDa4pSlj)^eqh)J+21utJtkQNH%pm4%wjX&8WS`d<%fr0(g0Va~#0;LpHVB zWL-`}+A-U+Mng3QP3_N{>?3o?Szx}tUK!_x^6ia(-gr89ou}Y4ssDOg{@V<#Wjy+t z&6a@myIGs5EzNnO)tN239-Xr+**o_#%_S*|bgQ0wI|pWaz$_JglU>b5t?o=WW>0I= z{RBU=Kf~8}`vzA-ubsU*YCEz!hN^8c|Ec&I^Zf=|x3d7=0GT1U43`#M4oOB{0Qm~^ zU07exs@vo-$TyD8K^`43+hg_nV#q7fn}Yixi*i4#bjbRWjhFVWwc#^gtHeuYo5s(Z ziHvm0W*`_nh>YxR90cF%=iaPERbLjXwNBL-o7pakuik77h^}@oq@m*`t20y?8yB-f z>&s@Ehs4*0zXo1bXRlSVrifPs=Ex?efU1oyR_JZR9@?qw=kd|)G<93`)Gfk&D-Iqn zT#Cmz$j-Ol3E6Ni>swizxemY&V{?miPeNYb)~{jD85idC<0*NM9SmtE@?q|WzMSymyI`FU~|SZ~mZ)AS5v?Ru+2W}`~u zj&WkGL)AHYX_!rW>S%G9?eza>@fg#o*M9rzm(|1i5vyOdT_ZhhKhxJg3z<#0RN**e z#_5M3+vK0XVZZbIQJ3qoM*w^PvhT|#;2r=!2U$qWpz2eZ4@JB)x@f@IC+9&jmCUy%P1yOVLbzX zWP~v^nGTifnGTsAQP8M#D5jUyfnCp>GO|&mOC-;Ah=ML&+j;zlbkZtqHAq+dywcu1 zeW2?1`u9x$-jD6ieC)#UD1dLp!OTn6x4rgxIpo#oP0zOUw7)H@_RpMem40Y>Rq!I-OxIAU%-|Vag?Ck#p0Ztl zA@!@$j^)!^K1B8yzC-AH>@bJVOu_SY0RA_&pET^s(UOuQ{k?^65syeF92{Lgk2j=Z3BV{}V{qivAA(rb0` z+R(OLv{P-bEty|1AJo?@zsP48Z@{mo?HA0hOa|k543fOO6h{Ea2O8f1NeVs%Sp$># ziEZb70M|qIbh%|FJ-bfTcbT5q_)=~6p*+~NEH3x>G1Cj`H-#xPt1%hk zf*e(vZNQwF>{vUF!HwuE_(R&HSLdm0xDDUA62MPj-kE_5@pu5TVE4KKHeEp8Dth~j z`n@0Wn6K(Hy|K*F^x*6N5pE9*!JnfaYh8N#{x-*lUZ}RChd-t5w`#L!=Ufe5M#Zx6 zY-c|2ZnFX{%WJQaMRW^;KNWcOW_GF8%R+_D!>QP_M=#s%89lr6u=rWqd3-^1VP#eR z8BXTUJ-*um`;hMy-401&jzHjQ0DlXz*!JU)y;7>MgseZg0l+t4{1*HcP67CB$WFOd zFV9bG;*&x1$07JyrUyg&WTu0T1C>74gWqWM#-`c$!tkTMJXb&0{JmKnEni=c@EchC zo^dd^J8X*$~2{&hGjZs z)1;9;UY#4?mjL(@0MEb?Xt)NlC(9Yg4!frix4mxveaJ^0UxDdAy!c)KKLdH3#rhA3 zPM*Hr5j~QPVxZTbDmp}cu@XDs(0KMhL5`+nW5UAlv%FY5^Wv3_`C0s}#vNU5_n)!6 zSUXmB{bhFTY12v^)wc5ds?mVZcz$1L*Ay1!x0h~6S>;;0K8C&*rsg-6?-crs;W3px zhVZHQMh}k#a(}AASRUUD84Q<4$J%iY@_O@IARk@qvGt1p{FjOKc>wb2_6;3+Y!a&W znacm?ijk45NbfnufGKU%(>_z;jo}m7y0;y=>osPu$dZ|sDOUJJc;22N?0PQ@seh(V z#@B1uq4lWjdy-wtWLrKxv=zQpU&&-!J)^x+7>|8*^y-r7*30W&$nL90unujXmv0B~ zZ8*HqTLzy4@TU{&^M{bPz#bVuJ7zG7{7-}Di>$x&`v1^aHr3#&XV$%aMy6aU5b^A( z6Wc3ih|Do~5wMtC9rHc;J$f+axGzTaYrZepzSm{DsjlKgf7RewW$Yvoq5v z3v^cQJvd5SA~+7&o8{XfkBfd0@|ge+ntdOGY()1t$ZXA6_#}Ye1@M>P{kfVJ@Wrby!0T8$zGhc^epzUm=KKzQGcw)eWq(QnelAu=@RLk#lT3mE@M0^ zu}uGu+Q`#|;jpop>65}>LPA%$OJF!XvU~L%ll@1uQ{7ecK$H#7&3{N6Rd`1@y?o}j z!&I`ahHO)R4%>e;v&+XB0DlDFTTowc`!YSkdG4FCeM7@^)qJhq ztX>O(pVf&i7D7OyGjq>&RxSulv|!KDcrv}kbQPJF4{LwhMxNdc9|V7&&{;jb1zeUl zv-h6ip=Db+o-Z)J^=xNlMSaa4X90XMfLEjMQOKnR#~=%sUjSLG`$@$8bqV=+t8A+ssEJy{!{fP4e#{788}1mOAD3{-q| z=(QgD%(mNr9z81hGaT=KMb4ZM>Dr4wbbPmVtn%sgw-mYeS`SZaxL%pt>?~ts&Z+Mh z=bcNBO~BmkF-LuRc)kwu-J5ME1sBS34!}DB+=TeC(E{>z(ZeHTy%)eMk;ky1FlG?R zV(OGSZ!_Kug~{?p^L?_)ydKyWWSwiddEZfrO`{cjI_ZIwm{2D}y zcWmeM26k2#uTw`n*soVs(ZQByGX?t!-&<6+2yi@^o;{|_+ADUmx_JD&`ZC@X|M3>z zdUmSl5-l#a`1b(#w1aa5>u?;h*5&(f_`62TzfVCH)DD5O0Dc6r37%f$>iL@fU-g}R zf@{kxUm%a+-U8CBk9oSYg`Gp6_6NA+5ymseN2U^I$Fj8~5yj7Ns+)g2C=)x{fc z?YYOFU5|XHr>#7^sy?BjQCWp?6yPiJb_Jpa-!+&^zg@3)2Aj}-jEoZiz8~A4$+!@Y z??wF9(2bDfV+ijbhs^4DaMUm6lX0Qj_6Q~bz2*M`@q#dKu_!#TI3@vZdmu zY4o*hLF&@{MvIIrO=a;~W(&5^%Cn`GZ|lJ9rSX{VY%!GO1qa8gTV!|5KccC&QM7n9 ztFK32tzXn`%vYFCu=;AQQ9i^rL*D`Q2bmkT{v?!r0u%7*anp_vP&)L|^IF*cn-UhnmcW@>v(2~*a+g8TIV z{s4#X_>Yd-aVO-_5li}xL)N+U@H@HUcR6;e|4#)|`|cDl<=C?+*p>Edu)uD%*X%;r zhC5zT;%%rC@$S{5B4chR?x|-czt?6FebxqJlL{*@)2GUtZBAFwg_Tt{?ivbX+p3q> z=OAk-j-VfIgRFOXE!G$7?n5^CyQj$O2>?F};P)UiVLh9}d0>5i(-8HWO3a!fmP|=A z)Q)r9i1qTDbHI-_&6`S(P5JTykj|_J3g*ZQ^WUCF1C6&!pXHhDL^z~_dAdfp+W73e zs)M(vGunC5^3*t98!()TgGTZ!*j)@Qz11y}>*>~`yWPEUVahz(9^cB^-qVZGMD53P zx3<0?GIMYQ{jh-SgY)f>9dqA@!*)Ik;3EKTM%>O%0{C+PKL$x)8gEag=L;69{^j|G zmKViwCTpLRSv=OytX!)L!1eHAVg^>93a(c-50~j`%UJy*$YNSGd5PNI(p3CF(`7yp zjZa?tv$$;agDH!2WwAZ9{m{&q&2)IPA9H1yT5d&##;fA@>Qa$EXVzWSrH7`PB+MaW zD*kiOjRozCR|0r5WSz#gAH7_t$9({P6!Lu|ZR0B;3vHv_iO)m6`21~{*B_#REc<2j z+wxrtQ|U2P%#Ca~mHZx>A@!On?nbOvo;;&lsW4r3_Dlyan_mWcKO_9K@a%0C)rZSokRb?^qpYG0rC< z$l_S^%jk#3)FBY@oJv*?pGrLGiTAzo8$^q#hw#mGuJU5~L_XF#CQb>IFU!*H?1P;) zw9`hc%<}fKHaoQxP0caA?bMT}yT*+&NK5M-8rT$;hab&GMYC0&Y-TUkh8cg$GitjE zUB-ifM-$mG@>OdO#@F(*=S;VrHm%Y|HU)r(0DO?>bp&;|4ZuGH@b@6!folHok$~oY z0KWy`ze651dDGQVJgN9w2n%rUZ`57}OR+mBo>^y3_WI{>^M2l3@r@W*hE1NbEXuSr{H9V!EX zE#G9nor-oFeKkr{vhrS>p|B|%P7&v(jFr_qqK6mdUCp){*vxTZ%I)k+wD{9YYN7>3 zUPi{svU=&n%9B;e3|W0Vyez58vdl`B>Sfc}FO#3qF@LcCvsn*Iz>NnvCrhuCu`?CBA zWRt&r0Pg|t130|jOM|HG7^50X;%hIyU($YoQUNy7y_`RbPgi-644R3sRQh zGabG5vV1)LOy`V`R}W9m%#R`*=3kL-_Sind_i)G5)zcs3+|#}JKO$w zYX{aq+NMm0sIz#wG#gu8y!x`bGFwKvWVZC2liAjj6Y*!h5w)}Z#6(oj%!c-wt}D~i zljmKt^|Ac+A#cBY7wR`1M^J<30C*U{#{fJE?#rx=^o^TtH|;Nx|JvB;`Ii?%qZq|- zGTu?l@)9jJZg~9{r0#aiun!laUyF|TZbrScwqcKov`=Rou_Fd+SL*rFO z+Y>Lw!qhQtXuPk)+&S&SbeRH%@(KMcx@)s{8X9bd)UqRsYcsBf7iD^$j7YzRZ!OL4j^Rgl3l(0r zzu3OTc-eMnzh4O8%P`-7da1&V5a0YbfO{axA&|$S2G#!9Ao54n?mfWz^ia_Kkm;8J z8waZWZpd|jw}lt$dU!CaR!xxsL#TyLtVJ`Ef+w%QK^o;-dBKstk+MZ0Ggk23}ufeb>{S z>1_L0M5oJ;)LFOt5SvHzOz+G#)pCzd6mRVqpzUMr2&~sD8jqNNu{O6pb#S8oFU)^k z9$jO2m2#$wC&$y-!)4Hm-$U1*49*@#|@SPyb9-1U+#uvdfV6>d}i`V|w-QUi;rpyxs1YAa5tdeRHk-w>&M51#d4E zi<|w|ygYuDMvROd?V>nTp537_>I9iBJ*ezcq4B&810!ek{6t^3yqF(qUG^QEtixn7 zn9VI7^Ed1F9*(C=1+@G|`v_#m*Rw?)N6-hi1Ni#@UcUOD4Zz+en^8HtUh(aypKE{1 zHZWtf`a0`VHr`~3Qq|X^zUcAy;w7WAgS{RXvbgE-)%?A&Ps_4;dypk$bSY)bMDc2_4Ueh z`NHVwId-OtmB;8APQ?xluj%UP;{7r?UfWmjJzG}KBfjifrpv;?t?E)~1MS1r_N&Oe z4!~=%dwY*uEbtu2SEJtpNf23kdF{mFmc^;^8q+T#Sy9}H`gImV7*F=!>w6wA9e1Pk zAQtRw8q=N0?uoBe954R$*wh=FD>`Ly(&H7$>>ZDzYuOn1`Ro55)Nuc)$ah`!00000 LNkvXXu0mjfyYF&r literal 0 HcmV?d00001 diff --git a/data/debug-interface/favicons/mstile-310x310.png b/data/debug-interface/favicons/mstile-310x310.png new file mode 100644 index 0000000000000000000000000000000000000000..28ac28720452d81acbbbc7e51afe2a72eaf3b0a5 GIT binary patch literal 65944 zcmV)~KzhH4P)wdO`JiB0(XdM(Y=dbUZ?|UB=8p|&f-b%;VI&3a2 zebYaLcB~|ioc8U4uKl}9{-yO&Qa7n_Zh1chO7o8KvrzbwwvUBz>wA^QdY`nH_Frp% z9UH&Np}i#kF6FhP*QcT*D{adl4<+7paHqmr8n`wMC2?~);+O=d8t5_z$5t0L>FKL% zJ8A26C|Z_X<{`_u%HwjZeZOX%4!!uviQl(CmmMLt;^;d0rUr{u2&q-6rQ!QZYbZMU z_?8pKf-Y^?hsGdxwb5mD()VDmp}mNeZ<*t-1a5h1w{4DwtM5rImVd3qVJg4Sw=qn% zISb~JF;`>$OT|sSkL6Q~M_RRFzA#1FmYUydRi+hvYkgAhau`4_3M)>!G2$GCHPG6QQz9eQHzioWt)=0rROEL#IH z77SI+ol>8xiWtLP)&x9;bZh6a3gciEXzT-Bh5F(QQ}4Q_mn$4~K`n_jSEXfL@eIM_ zd}-EN<<*8+(l*BJqkeZPLu$~ajY8@4S*N+e^(rn#mLUxErN!za?cDro(UQ~m#?%*T zr`ub54y{@)O=oQ3Crp?yVa%9#+G=BJzY!ou_^F|VDcL_P$)hi6wCkR1t?;X&LavRW z1bRyzLue)X=o3S!j>n+Y94h_3G%S6#RTq1Q+$r0#k3x9o;wFW)Q5_EGh zmU`)m>~ic1eAtRaa=*3TtvTP_-@Y_Ld4{;e zH0HErDqSCqKH5XH#>#0$sGp?j$CqzvOr_$-X!GS^Ny|5mV`a0HCq!RPzqh;(g^T@- zy(99j{ocZh-0wMKIyFvxeKIw!V>G5{_T`_`e!eiVab-y(R0kzAh3LwOlT-Fs8mayj zdmp03(s!&h`o7f|%dzsO>cyOiDY7SwrQkUo$CBrE$2#zHz{8v_xHQ7cKSlN~ebh~# z^*wZ3*3NGg`(n+pXw7Hnbi3reifwAeSb6WV>wMYyZ%6cAr+p9dRG3l;xNE+-aceY0 zZW=S-Qs862N&JFKBfPvF`FXLf4*EoC{$rrMZ*2GSEdzbm>DbzAOywP-ZpK8dHq$Xp79MfokIaGN&5l#-85+E;P~~qsiJYe6(BQq}tC{ccJ=>rDyG1p?JRE zK9rOv6wjB&41XPj;#l&Ip>pmw=DUT}c3$bq&o>dJw z3}l%Y0}U2j0DJ|T(9%3Vi?)|S=&S6jP^YUvJg)3@yWC*-%mwrw+u^w#Bj z%`juYyMZUk6I`AGegp|U6HdjdwEKi^nA&;5gzi}BaWo|HU9~gT@O_u5R{FmV93f9| z*#f=*ybIW0iH@;gr3VtLPycp8$u>_;TD4%^cBoB9?K1Vbpq$24KUnsBT9j_?o@KAZ zB;w}oFD^?M%jpOgpd-++(?p@?1n_>~&5X}j*9Yr#LVon_KJLP0JVFr6KmsmzR~s6s@8D znLD6!>LOJ)q461t8;fHNn_^a>G%bIv`CIBG#S<)T6zd}~dQ<%_RhO}Piy@YuFMSIw zA)2gX%J(hR7rLZrp*2?K&^rqqDY`;5#QL%i)_&#t?W4h$PAE?+PspjqPOw&F4HoHtLcH9TaZd8evM}<}hqudVTeczWbadpP^_N3d?A# z6n`5-{~2pLkCm?4u*`vd6}KbLUfsUEJ8uoi8Hs-b0l4BdY6-bnke*q z8u;7jz9VbdO4_<_fu%M|+GXfGL-EH{k2@K)+OtO5C46v5)EsYJd2>!(4Ke2WNV_i{ zUNc^`jJm32N>o^G{8ZXq(#Q#u6EAll#RkKE;OnU)v^37?J_x)MdDhLLvlLdwkjrfQ z6ugE=uMcK2q(Ie++BT9`pW$=U8Ed)w&c9?a*(JYPSf-G_YC=vs?LNnNr?lG*>T6v0 z|JZLgd@QY4m=flkBa!FiVHJEV^$?>w^!)


G~mY@w4${|&e$LU)K(x1Yp1cc@-s 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 literal 0 HcmV?d00001 diff --git a/data/debug-interface/favicons/mstile-70x70.png b/data/debug-interface/favicons/mstile-70x70.png new file mode 100644 index 0000000000000000000000000000000000000000..fe3ff757cadf63bb56292398ce5aad81d0f7821d GIT binary patch literal 2957 zcmV;83v%>{P) ze~47q6~{k)8Me!^ELMVDmaxboiv+QYSXr#JQra|#^p8Xq+olqN6tQWMr4_M3C}~(k zM1qI}5fMpK5fKqeO9$~1>U<;5qaK~`ig=IVEs0Q+fOiTqv>Tt2pC+7>xX{X+!(L!_o7xrx=w^5dG5IKw6(afW;=bHh>(a6OTBb$Nc)qnTVyg)R} z>)|r66Q!C*(d#1U=)=fGI?y-xLW1Ys3LF4_0Q{-?*%)vb6^O*i|A4;%zeU9)!@v&- z9wz<(_#W_=2-nh$6#p?`S@r*)0sjF$s{Y2mBAh=rti^p&cj21YK{OK;@SaDQwi4{7UI`rF`-FEk{bUY35QV9VejfkE9>X0eI7lhZ zk}X9jqo9_##=UL0zN;uZntRsJys=g%MMgd?>;>T3IH?K_jLIBBNHCgv;7Q3(f)u;0+P3ik z-#HuN-t{5HDGbX{fap5yGucU5fn_KW)ap=ocg=lpfE{SOe*;Aqy?mJEzqT;1JsXV=8;3YkS9?htq>eS=Il6fhRiZ?C152o zreVi}hZK4RtqnFshmh6svs7go zPgQeJ2Jq_(K0Au0(-)34WUCXS%6PS1uQoYuU4#44i)KgHE|_V?|8dt(){&NJ`77{? zlzux2o<{fbe3RoAz5)!Rz(0V0SO4z-KL>t8feT1WG=F09BC}{%*N=aeaF54*aF8D` zUh~;%G_@|#r#}nyQNNf}p2ds?-tsx-RgZhnkE)o>oP?h0J!#9v8fkl%pCa@5ZnFb( zz&B8a@6SHRcuiCP3Gh2KXP|`2#s3ccI)Q7;S>)`VM5*7jM`5|37u5{p!5SQ| zUi0Ca&t_01&=?x)TT>sB5mX$Rb|?GEnd-Gppr`!^^(kOWM9j4E_ej69z2sc=I=7+t zzBTa)(Sz#gqOK?!x0s?&+wpCp4=F-cqKICxeoGtZK_S>{q+48iB$kL#A>60^ zA$k>T#9b43IeJeg5mYi&L6#I5!g~_xO*C3C*|t?QkJks4JJ{i0>Xgttf|GcsWbdLN zjoGj&&VUa8s3xHbBt#1l|jIH|*u0z+uh$vEzgWZh`y?M>=C z>;Y~e=Mb8u8@BV!s3H(Kh|l0nS!t8ps9 zC9D&eD~=Ga0#s0z(2^6@6aTcZ+Z13o&rYF4GHVRkB9I)hllT?jHU-+^z32ql)hme9 zZUB{AiW&!~Wfmzx+%tE-h`T71CF49s{QC?|;qH2tTROo4fR?5I67aPc&)JRY2k*pq zPD_IH6TdI8zpX7ufKIUh0RKfXf$zk4&UsWFWXTCV#JeZK$Jo$t?$|_p(ZLxslgN@I z9OB!ptc>;zw&aWf>I*%iNUrzw?bOodkANSe!jY(0A0VeV#FH+z)5CI1FIwIuZ0FBo z*9OWx!-NkIO;f+&vn8hlT^7d3Jv!HqDjd5At^gNPxl&6a1YH}bf>sx^6o@VwZ~5jW z-%95)ElJXi7Jq2g`Gu$luz1so5}a-LZA&5O#y@9Z=Ld8EU1+tCg`IyN1(7TrfP+>L zt4$%>wShYf2dzFfgQA9Zoq!Hy6zw=-u~;k?OWyfEiwASCl^Kig00000NkvXXu0mjf Dx1WtE literal 0 HcmV?d00001 diff --git a/data/debug-interface/script.js b/data/debug-interface/script.js new file mode 100644 index 00000000..def30e22 --- /dev/null +++ b/data/debug-interface/script.js @@ -0,0 +1,152 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * * + * Copyright (C) 2018 Simon Stürz * + * * + * This file is part of nymea. * + * * + * nymea is free software: you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation, version 2 of the License. * + * * + * nymea is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with nymea. If not, see . * + * * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + + +/* ========================================================================*/ +/* Websocket connection +/* ========================================================================*/ + +var webSocket = null; + +function connectWebsocket() { + var urlString = "ws://" + window.location.hostname + ":2626" + console.log("Connecting to: " + urlString); + + try { + webSocket = new WebSocket(urlString); + + webSocket.onopen = function(openEvent) { + console.log("WebSocket connected: " + JSON.stringify(openEvent, null, 4)); + document.getElementById("connectWebsocketButton").disabled = true; + document.getElementById("disconnectWebsocketButton").disabled = false; + }; + + webSocket.onclose = function (closeEvent) { + console.log("WebSocket disconnected: " + JSON.stringify(closeEvent, null, 4)); + document.getElementById("connectWebsocketButton").disabled = false; + document.getElementById("disconnectWebsocketButton").disabled = true; + }; + + webSocket.onerror = function (errorEvent) { + console.log("WebSocket error: " + JSON.stringify(errorEvent, null, 4)); + }; + + webSocket.onmessage = function (messageEvent) { + var message = messageEvent.data; + console.log("WebSocket data received: " + message); + document.getElementById("logsTextArea").value += message; + }; + + } catch (exception) { + console.error(exception); + } + +} + +function disconnectWebsocket() { + console.log("Disconnecting from: " + webSocket.url); + webSocket.close() +} + + + +/* ========================================================================*/ +/* File download function +/* ========================================================================*/ + +function downloadFile(filePath, fileName) { + console.log("Download file requested " + filePath + " --> " + fileName); + var element = document.createElement('a'); + element.setAttribute('href', filePath); + element.setAttribute('download', fileName); + element.style.display = 'none'; + document.body.appendChild(element); + element.click(); + document.body.removeChild(element); +} + +/* ========================================================================*/ +/* Network test functions +/* ========================================================================*/ + +function startPingTest() { + console.log("Start ping test"); + var textArea = document.getElementById("pingTextArea"); + var button = document.getElementById("pingButton"); + // Clear the text output + textArea.value = ""; + + // Request ping output + var request = new XMLHttpRequest(); + request.open("GET", "/debug/ping", true); + request.send(null); + button.disabled = true + request.onreadystatechange = function() { + if (request.readyState == 4) { + console.log(request.responseText); + textArea.value = request.responseText + button.disabled = false + } + }; +} + +function startDigTest() { + console.log("Start dig test"); + var textArea = document.getElementById("digTextArea"); + var button = document.getElementById("digButton"); + + // Clear the text output + textArea.value = ""; + + // Request dig output + var request = new XMLHttpRequest(); + request.open("GET", "/debug/dig", true); + request.send(null); + button.disabled = true + request.onreadystatechange = function() { + if (request.readyState == 4) { + console.log(request.responseText); + textArea.value = request.responseText + button.disabled = false + } + }; +} + +function startTracePathTest() { + console.log("Start trace path test"); + var textArea = document.getElementById("tracePathTextArea"); + var button = document.getElementById("tracePathButton"); + + // Clear the text output + textArea.value = ""; + + // Request dig output + var request = new XMLHttpRequest(); + request.open("GET", "/debug/tracepath", true); + request.send(null); + button.disabled = true + request.onreadystatechange = function() { + if (request.readyState == 4) { + console.log(request.responseText); + textArea.value = request.responseText + button.disabled = false + } + }; +} diff --git a/data/debug-interface/styles.css b/data/debug-interface/styles.css index 8baf78c6..0397a77d 100644 --- a/data/debug-interface/styles.css +++ b/data/debug-interface/styles.css @@ -20,120 +20,144 @@ html, body { - margin:0; - padding:0; - height:100%; + margin:0; + padding:0; + height:100%; } p { - color: #676767; - font-family: "Ubuntu", Helvetica, "Helvetica Neue", Arial, sans-serif; - font-size: 100%; - text-align: center; + color: #676767; + font-family: "Ubuntu", Helvetica, "Helvetica Neue", Arial, sans-serif; + font-size: 100%; + text-align: center; } h1, h2, h3, h4, h5, h6 { - font-family: "Ubuntu", Helvetica, "Helvetica Neue", Arial, sans-serif; - font-weight: normal; - color: #676767; - text-transform: none; + font-family: "Ubuntu", Helvetica, "Helvetica Neue", Arial, sans-serif; + font-weight: normal; + color: #676767; + text-transform: none; } th, td { - padding: 3px; - padding-left: 10px; - padding-right: 10px; - color: #676767; - font-family: "Ubuntu", Helvetica, "Helvetica Neue", Arial, sans-serif; - text-align: left; + padding: 3px; + padding-left: 10px; + padding-right: 10px; + color: #676767; + font-family: "Ubuntu", Helvetica, "Helvetica Neue", Arial, sans-serif; + text-align: left; } hr { - color: #efefef; + color: #efefef; } table { - display: table; - border-collapse: colapse; - border-color: #efefef; - width: 100%; + display: table; + border-collapse: colapse; + border-color: #efefef; + min-height: 100px; + width: 100%; } button { - width: 100%; + width: 100%; +} + +textarea { + background-color: #3a4055; + width: 100%; + padding: 15px; + min-height: 100px; + text-align: left; + border-radius: 10px; +} + +.console-textarea { + color: white; + margin-top: 20px; + padding: 15px; + font-family: "Ubuntu Mono"; + font-size: 100%; } .nymea-main-logo { - left: 0; - height: 85px; - min-height: 85px; - max-height: 85px; - vertical-align: middle; + left: 0; + height: 85px; + min-height: 85px; + max-height: 85px; + vertical-align: middle; } .warning { - background-color: #ed3146; - border-radius: 20px; - opacity: 0.8; - width: 80%; - margin-left: auto; - margin-right: auto; + background-color: #ed3146; + border-radius: 10px; + opacity: 0.8; + width: 80%; + margin-left: auto; + margin-right: auto; } .warning-message { - padding:30px; - margin-left: 60px; - opacity: 1; - color: white; - background-color: transparent; - font-family: "Ubuntu", Helvetica, "Helvetica Neue", Arial, sans-serif; - text-align: center; - float: none; + padding: 30px; + margin-left: 60px; + opacity: 1; + color: white; + background-color: transparent; + font-family: "Ubuntu", Helvetica, "Helvetica Neue", Arial, sans-serif; + text-align: center; + float: none; } .warning-image { - padding:12px; - height: 60px; - min-height: 60px; - max-height: 60px; - float: left; + padding:12px; + height: 60px; + min-height: 60px; + max-height: 60px; + float: left; } .warning:after { - content: ""; - display: table; - clear: both; + content: ""; + display: table; + clear: both; } .download-row { - width: 100%; - height: 100px; - left: 0; - right: 0; + width: 100%; + height: 100px; + left: 0; + right: 0; } .download-name-column { - float: left; - width: 30%; - padding: 10px; + float: left; + width: 20%; + padding: 10px; } .download-path-column { - float: left; - width: 40%; - padding: 10px; + float: left; + width: 40%; + padding: 10px; } .download-button-column { - float: left; - width: 20%; - padding: 10px; + float: left; + width: 20%; + padding: 10px; +} + +.show-button-column { + float: left; + width: 10%; + padding: 10px; } .download-row: after { - content: ""; - display: table; - clear: both; + content: ""; + display: table; + clear: both; } .button { @@ -146,34 +170,45 @@ button { display: inline-block; font-size: 16px; border-radius: 10px; + opacity: 0.8; + transition: 0.3s; } +.button:hover { + opacity: 1 +} + +.button:disabled, +.button[disabled]{ + background-color: #cccccc; + color: #676767; +} .container { - min-height:100%; - position:relative; + min-height:100%; + position:relative; } .header { - padding:10px; - background-color: #efefef; - text-align: center; + padding:10px; + background-color: #efefef; + text-align: center; } .body { - padding-left: 15%; - padding-right: 15%; - padding-bottom:120px; + padding-left: 15%; + padding-right: 15%; + padding-bottom:120px; } .footer { - position:absolute; - bottom:0; - left:0; - right:0; - width:100%; - height:100px; - background-color: #efefef; - color: #676767; - text-align: center; + position:absolute; + bottom:0; + left:0; + right:0; + width:100%; + height:100px; + background-color: #efefef; + color: #676767; + text-align: center; } diff --git a/libnymea-core/debugserverhandler.cpp b/libnymea-core/debugserverhandler.cpp index 41899c06..92cf1f12 100644 --- a/libnymea-core/debugserverhandler.cpp +++ b/libnymea-core/debugserverhandler.cpp @@ -24,15 +24,363 @@ #include "httprequest.h" #include "loggingcategories.h" #include "debugserverhandler.h" +#include "stdio.h" #include #include +#include + namespace nymeaserver { -DebugServerHandler::DebugServerHandler(QObject *parent) : QObject(parent) +DebugServerHandler::DebugServerHandler(QObject *parent) : + QObject(parent) { + m_websocketServer = new QWebSocketServer("Debug server", QWebSocketServer::NonSecureMode, this); + connect(m_websocketServer, &QWebSocketServer::newConnection, this, &DebugServerHandler::onWebsocketClientConnected); + // FIXME: enable disable server with debug server + if (!m_websocketServer->listen(QHostAddress::Any, 2626)) { + qCWarning(dcWebServer()) << "DebugServer: The debug server websocket interface could not listen on" << m_websocketServer->serverUrl().toString(); + } + qCDebug(dcWebServer()) << "DebugServer: Started debug server websocket interface on" << m_websocketServer->serverUrl().toString(); + + m_timer = new QTimer(this); + m_timer->setSingleShot(false); + m_timer->setInterval(1000); + connect(m_timer, &QTimer::timeout, this, &DebugServerHandler::onTimeout); + + //m_timer->start(); + + qInstallMessageHandler(&DebugServerHandler::consoleLogHandler); +} + +HttpReply *DebugServerHandler::processDebugRequest(const QString &requestPath) +{ + qCDebug(dcWebServer()) << "DebugServer: Debug request for" << requestPath; + + // Check if debug page request + if (requestPath == "/debug" || requestPath == "/debug/") { + qCDebug(dcWebServer()) << "DebugServer: Create debug interface page"; + // Fallback default debug page + HttpReply *reply = RestResource::createSuccessReply(); + reply->setHeader(HttpReply::ContentTypeHeader, "text/html"); + reply->setPayload(createDebugXmlDocument()); + return reply; + } + + // Check if this is a logdb requested + if (requestPath.startsWith("/debug/logdb.sql")) { + qCDebug(dcWebServer()) << "DebugServer: Loading" << NymeaCore::instance()->configuration()->logDBName(); + QFile logDatabaseFile(NymeaCore::instance()->configuration()->logDBName()); + if (!logDatabaseFile.exists()) { + qCWarning(dcWebServer()) << "DebugServer: Could not read log database file for debug download" << NymeaCore::instance()->configuration()->logDBName() << "file does not exist."; + HttpReply *reply = RestResource::createErrorReply(HttpReply::NotFound); + reply->setHeader(HttpReply::ContentTypeHeader, "text/html"); + //: The HTTP error message of the debug interface. The %1 represents the file name. + reply->setPayload(createErrorXmlDocument(HttpReply::NotFound, tr("Could not find file \"%1\".").arg(logDatabaseFile.fileName()))); + return reply; + } + + if (!logDatabaseFile.open(QFile::ReadOnly)) { + qCWarning(dcWebServer()) << "DebugServer: Could not read log database file for debug download" << NymeaCore::instance()->configuration()->logDBName(); + HttpReply *reply = RestResource::createErrorReply(HttpReply::Forbidden); + reply->setHeader(HttpReply::ContentTypeHeader, "text/html"); + //: The HTTP error message of the debug interface. The %1 represents the file name. + reply->setPayload(createErrorXmlDocument(HttpReply::NotFound, tr("Could not open file \"%1\".").arg(logDatabaseFile.fileName()))); + return reply; + } + + QByteArray logDatabaseRawData = logDatabaseFile.readAll(); + logDatabaseFile.close(); + + HttpReply *reply = RestResource::createSuccessReply(); + reply->setHeader(HttpReply::ContentTypeHeader, "application/sql"); + reply->setPayload(logDatabaseRawData); + return reply; + } + + + // Check if this is a syslog requested + if (requestPath.startsWith("/debug/syslog")) { + QString syslogFileName = "/var/log/syslog"; + qCDebug(dcWebServer()) << "DebugServer: Loading" << syslogFileName; + QFile syslogFile(syslogFileName); + if (!syslogFile.exists()) { + qCWarning(dcWebServer()) << "DebugServer: Could not read log database file for debug download" << syslogFileName << "file does not exist."; + HttpReply *reply = RestResource::createErrorReply(HttpReply::NotFound); + reply->setHeader(HttpReply::ContentTypeHeader, "text/html"); + reply->setPayload(createErrorXmlDocument(HttpReply::NotFound, tr("Could not find file \"%1\".").arg(syslogFileName))); + return reply; + } + + if (!syslogFile.open(QFile::ReadOnly)) { + qCWarning(dcWebServer()) << "DebugServer: Could not read syslog file for debug download" << syslogFileName; + HttpReply *reply = RestResource::createErrorReply(HttpReply::Forbidden); + reply->setHeader(HttpReply::ContentTypeHeader, "text/html"); + reply->setPayload(createErrorXmlDocument(HttpReply::NotFound, tr("Could not open file \"%1\".").arg(syslogFileName))); + return reply; + } + + QByteArray syslogFileData = syslogFile.readAll(); + syslogFile.close(); + + HttpReply *reply = RestResource::createSuccessReply(); + reply->setHeader(HttpReply::ContentTypeHeader, "text/plain"); + reply->setPayload(syslogFileData); + return reply; + } + + // Check if this is a settings request + if (requestPath.startsWith("/debug/settings")) { + if (requestPath.startsWith("/debug/settings/devices")) { + QString settingsFileName = NymeaSettings(NymeaSettings::SettingsRoleDevices).fileName(); + qCDebug(dcWebServer()) << "DebugServer: Loading" << settingsFileName; + QFile settingsFile(settingsFileName); + if (!settingsFile.exists()) { + qCWarning(dcWebServer()) << "DebugServer: Could not read file for debug download" << settingsFileName << "file does not exist."; + HttpReply *reply = RestResource::createErrorReply(HttpReply::NotFound); + reply->setHeader(HttpReply::ContentTypeHeader, "text/html"); + reply->setPayload(createErrorXmlDocument(HttpReply::NotFound, tr("Could not find file \"%1\".").arg(settingsFileName))); + return reply; + } + + if (!settingsFile.open(QFile::ReadOnly)) { + qCWarning(dcWebServer()) << "DebugServer: Could not read file for debug download" << settingsFileName; + HttpReply *reply = RestResource::createErrorReply(HttpReply::Forbidden); + reply->setHeader(HttpReply::ContentTypeHeader, "text/html"); + reply->setPayload(createErrorXmlDocument(HttpReply::NotFound, tr("Could not open file \"%1\".").arg(settingsFileName))); + return reply; + } + + QByteArray settingsFileData = settingsFile.readAll(); + settingsFile.close(); + + HttpReply *reply = RestResource::createSuccessReply(); + reply->setHeader(HttpReply::ContentTypeHeader, "text/plain"); + reply->setPayload(settingsFileData); + return reply; + } + + if (requestPath.startsWith("/debug/settings/rules")) { + QString settingsFileName = NymeaSettings(NymeaSettings::SettingsRoleRules).fileName(); + qCDebug(dcWebServer()) << "DebugServer: Loading" << settingsFileName; + QFile settingsFile(settingsFileName); + if (!settingsFile.exists()) { + qCWarning(dcWebServer()) << "DebugServer: Could not read file for debug download" << settingsFileName << "file does not exist."; + HttpReply *reply = RestResource::createErrorReply(HttpReply::NotFound); + reply->setHeader(HttpReply::ContentTypeHeader, "text/html"); + reply->setPayload(createErrorXmlDocument(HttpReply::NotFound, tr("Could not find file \"%1\".").arg(settingsFileName))); + return reply; + } + + if (!settingsFile.open(QFile::ReadOnly)) { + qCWarning(dcWebServer()) << "DebugServer: Could not read file for debug download" << settingsFileName; + HttpReply *reply = RestResource::createErrorReply(HttpReply::Forbidden); + reply->setHeader(HttpReply::ContentTypeHeader, "text/html"); + reply->setPayload(createErrorXmlDocument(HttpReply::NotFound, tr("Could not open file \"%1\".").arg(settingsFileName))); + return reply; + } + + QByteArray settingsFileData = settingsFile.readAll(); + settingsFile.close(); + + HttpReply *reply = RestResource::createSuccessReply(); + reply->setHeader(HttpReply::ContentTypeHeader, "text/plain"); + reply->setPayload(settingsFileData); + return reply; + } + + if (requestPath.startsWith("/debug/settings/nymead")) { + QString settingsFileName = NymeaSettings(NymeaSettings::SettingsRoleGlobal).fileName(); + qCDebug(dcWebServer()) << "DebugServer: Loading" << settingsFileName; + QFile settingsFile(settingsFileName); + if (!settingsFile.exists()) { + qCWarning(dcWebServer()) << "DebugServer: Could not read file for debug download" << settingsFileName << "file does not exist."; + HttpReply *reply = RestResource::createErrorReply(HttpReply::NotFound); + reply->setHeader(HttpReply::ContentTypeHeader, "text/html"); + reply->setPayload(createErrorXmlDocument(HttpReply::NotFound, tr("Could not find file \"%1\".").arg(settingsFileName))); + return reply; + } + + if (!settingsFile.open(QFile::ReadOnly)) { + qCWarning(dcWebServer()) << "DebugServer: Could not read file for debug download" << settingsFileName; + HttpReply *reply = RestResource::createErrorReply(HttpReply::Forbidden); + reply->setHeader(HttpReply::ContentTypeHeader, "text/html"); + reply->setPayload(createErrorXmlDocument(HttpReply::NotFound, tr("Could not open file \"%1\".").arg(settingsFileName))); + return reply; + } + + QByteArray settingsFileData = settingsFile.readAll(); + settingsFile.close(); + + HttpReply *reply = RestResource::createSuccessReply(); + reply->setHeader(HttpReply::ContentTypeHeader, "text/plain"); + reply->setPayload(settingsFileData); + return reply; + } + + if (requestPath.startsWith("/debug/settings/devicestates")) { + QString settingsFileName = NymeaSettings(NymeaSettings::SettingsRoleDeviceStates).fileName(); + qCDebug(dcWebServer()) << "DebugServer: Loading" << settingsFileName; + QFile settingsFile(settingsFileName); + if (!settingsFile.exists()) { + qCWarning(dcWebServer()) << "DebugServer: Could not read file for debug download" << settingsFileName << "file does not exist."; + HttpReply *reply = RestResource::createErrorReply(HttpReply::NotFound); + reply->setHeader(HttpReply::ContentTypeHeader, "text/html"); + reply->setPayload(createErrorXmlDocument(HttpReply::NotFound, tr("Could not find file \"%1\".").arg(settingsFileName))); + return reply; + } + + if (!settingsFile.open(QFile::ReadOnly)) { + qCWarning(dcWebServer()) << "DebugServer: Could not read file for debug download" << settingsFileName; + HttpReply *reply = RestResource::createErrorReply(HttpReply::Forbidden); + reply->setHeader(HttpReply::ContentTypeHeader, "text/html"); + reply->setPayload(createErrorXmlDocument(HttpReply::NotFound, tr("Could not open file \"%1\".").arg(settingsFileName))); + return reply; + } + + QByteArray settingsFileData = settingsFile.readAll(); + settingsFile.close(); + + HttpReply *reply = RestResource::createSuccessReply(); + reply->setHeader(HttpReply::ContentTypeHeader, "text/plain"); + reply->setPayload(settingsFileData); + return reply; + } + + if (requestPath.startsWith("/debug/settings/plugins")) { + QString settingsFileName = NymeaSettings(NymeaSettings::SettingsRolePlugins).fileName(); + qCDebug(dcWebServer()) << "DebugServer: Loading" << settingsFileName; + QFile settingsFile(settingsFileName); + if (!settingsFile.exists()) { + qCWarning(dcWebServer()) << "DebugServer: Could not read file for debug download" << settingsFileName << "file does not exist."; + HttpReply *reply = RestResource::createErrorReply(HttpReply::NotFound); + reply->setHeader(HttpReply::ContentTypeHeader, "text/html"); + reply->setPayload(createErrorXmlDocument(HttpReply::NotFound, tr("Could not find file \"%1\".").arg(settingsFileName))); + return reply; + } + + if (!settingsFile.open(QFile::ReadOnly)) { + qCWarning(dcWebServer()) << "DebugServer: Could not read file for debug download" << settingsFileName; + HttpReply *reply = RestResource::createErrorReply(HttpReply::Forbidden); + reply->setHeader(HttpReply::ContentTypeHeader, "text/html"); + reply->setPayload(createErrorXmlDocument(HttpReply::NotFound, tr("Could not open file \"%1\".").arg(settingsFileName))); + return reply; + } + + QByteArray settingsFileData = settingsFile.readAll(); + settingsFile.close(); + + HttpReply *reply = RestResource::createSuccessReply(); + reply->setHeader(HttpReply::ContentTypeHeader, "text/plain"); + reply->setPayload(settingsFileData); + return reply; + } + } + + if (requestPath.startsWith("/debug/ping")) { + // Only one ping process should run + if (m_pingProcess || m_pingReply) + return RestResource::createErrorReply(HttpReply::InternalServerError); + + qCDebug(dcWebServer()) << "DebugServer: Start ping nymea.io process"; + m_pingProcess = new QProcess(this); + m_pingProcess->setProcessChannelMode(QProcess::MergedChannels); + connect(m_pingProcess, SIGNAL(finished(int, QProcess::ExitStatus)), this, SLOT(onPingProcessFinished(int,QProcess::ExitStatus))); + m_pingProcess->start("ping", { "-c", "4", "nymea.io" } ); + + m_pingReply = RestResource::createAsyncReply(); + return m_pingReply; + } + + if (requestPath.startsWith("/debug/dig")) { + // Only one dig process should run + if (m_digProcess || m_digReply) + return RestResource::createErrorReply(HttpReply::InternalServerError); + + qCDebug(dcWebServer()) << "DebugServer: Start dig nymea.io process"; + m_digProcess = new QProcess(this); + m_digProcess->setProcessChannelMode(QProcess::MergedChannels); + connect(m_digProcess, SIGNAL(finished(int, QProcess::ExitStatus)), this, SLOT(onDigProcessFinished(int,QProcess::ExitStatus))); + m_digProcess->start("dig", { "nymea.io" } ); + + m_digReply = RestResource::createAsyncReply(); + return m_digReply; + } + + if (requestPath.startsWith("/debug/tracepath")) { + // Only one tracepath process should run + if (m_tracePathProcess || m_tracePathReply) + return RestResource::createErrorReply(HttpReply::InternalServerError); + + qCDebug(dcWebServer()) << "DebugServer: Start tracepath nymea.io process"; + m_tracePathProcess = new QProcess(this); + m_tracePathProcess->setProcessChannelMode(QProcess::MergedChannels); + connect(m_tracePathProcess, SIGNAL(finished(int, QProcess::ExitStatus)), this, SLOT(onTracePathProcessFinished(int,QProcess::ExitStatus))); + m_tracePathProcess->start("tracepath", { "nymea.io" } ); + + m_tracePathReply = RestResource::createAsyncReply(); + return m_tracePathReply; + } + + + // Check if this is a resource file request + if (resourceFileExits(requestPath)) { + return processDebugFileRequest(requestPath); + } + + // If nothing matches, redirect to /debug page + qCWarning(dcWebServer()) << "DebugServer: Resource for debug interface not found. Redirecting to /debug"; + HttpReply *reply = RestResource::createErrorReply(HttpReply::PermanentRedirect); + reply->setHeader(HttpReply::LocationHeader, "/debug"); + return reply; +} + +QByteArray DebugServerHandler::loadResourceData(const QString &resourceFileName) +{ + QFile resourceFile(QString(":%1").arg(resourceFileName)); + if (!resourceFile.open(QFile::ReadOnly | QFile::Text)) { + qCWarning(dcWebServer()) << "DebugServer: Could not open resource file" << resourceFile.fileName(); + return QByteArray(); + } + + return resourceFile.readAll(); +} + +QString DebugServerHandler::getResourceFileName(const QString &requestPath) +{ + return QString(requestPath).remove("/debug"); +} + +bool DebugServerHandler::resourceFileExits(const QString &requestPath) +{ + QFile resourceFile(QString(":%1").arg(getResourceFileName(requestPath))); + return resourceFile.exists(); +} + +HttpReply *DebugServerHandler::processDebugFileRequest(const QString &requestPath) +{ + // Here we already know that the resource file exists + QString resourceFileName = getResourceFileName(requestPath); + QByteArray data = loadResourceData(resourceFileName); + + // Create reply for resource file + HttpReply *reply = RestResource::createSuccessReply(); + reply->setPayload(data); + + // Check content type + if (resourceFileName.endsWith(".css")) { + reply->setHeader(HttpReply::ContentTypeHeader, "text/css; charset=\"utf-8\";"); + } else if (resourceFileName.endsWith(".svg")) { + reply->setHeader(HttpReply::ContentTypeHeader, "image/svg+xml; charset=\"utf-8\";"); + } else if (resourceFileName.endsWith(".js")) { + reply->setHeader(HttpReply::ContentTypeHeader, "text/javascript; charset=\"utf-8\";"); + } else if (resourceFileName.endsWith(".png")) { + reply->setHeader(HttpReply::ContentTypeHeader, "image/png"); + } + + return reply; } QByteArray DebugServerHandler::createDebugXmlDocument() @@ -43,6 +391,7 @@ QByteArray DebugServerHandler::createDebugXmlDocument() writer.writeStartDocument("1.0"); writer.writeProcessingInstruction("DOCUMENT", "html"); writer.writeComment("Auto generated html page from nymea server"); + writer.writeStartElement("html"); writer.writeAttribute("lang", NymeaCore::instance()->configuration()->locale().name()); @@ -57,6 +406,44 @@ QByteArray DebugServerHandler::createDebugXmlDocument() writer.writeAttribute("rel", "stylesheet"); writer.writeAttribute("href", "/debug/styles.css"); + writer.writeStartElement("script"); + writer.writeAttribute("type", "application/javascript"); + writer.writeAttribute("src", "/debug/script.js"); + writer.writeCharacters(""); + writer.writeEndElement(); // script + + // Favicons + writer.writeEmptyElement("link"); + writer.writeAttribute("rel", "icon"); + writer.writeAttribute("type", "image/png"); + writer.writeAttribute("sizes", "16x16"); + writer.writeAttribute("href", "/debug/favicons/favicon-16x16.png"); + + writer.writeEmptyElement("link"); + writer.writeAttribute("rel", "icon"); + writer.writeAttribute("type", "image/png"); + writer.writeAttribute("sizes", "32x32"); + writer.writeAttribute("href", "/debug/favicons/favicon-32x32.png"); + + writer.writeEmptyElement("link"); + writer.writeAttribute("rel", "icon"); + writer.writeAttribute("type", "image/png"); + writer.writeAttribute("sizes", "64x64"); + writer.writeAttribute("href", "/debug/favicons/favicon-64x64.png"); + + writer.writeEmptyElement("link"); + writer.writeAttribute("rel", "icon"); + writer.writeAttribute("type", "image/png"); + writer.writeAttribute("sizes", "128x128"); + writer.writeAttribute("href", "/debug/favicons/favicon-128.png"); + + writer.writeEmptyElement("link"); + writer.writeAttribute("rel", "icon"); + writer.writeAttribute("type", "image/png"); + writer.writeAttribute("sizes", "196x196"); + writer.writeAttribute("href", "/debug/favicons/favicon-196x196.png"); + + //: The header title of the debug server interface writer.writeTextElement("title", tr("Debug nymea")); @@ -276,11 +663,13 @@ QByteArray DebugServerHandler::createDebugXmlDocument() writer.writeAttribute("class", "download-button-column"); writer.writeStartElement("form"); writer.writeAttribute("class", "download-button"); - writer.writeAttribute("method", "get"); - writer.writeAttribute("action", "/debug/logdb.sql"); writer.writeStartElement("button"); writer.writeAttribute("class", "button"); - writer.writeAttribute("type", "submit"); + writer.writeAttribute("type", "button"); + if (!QFile::exists(NymeaCore::instance()->configuration()->logDBName())) { + writer.writeAttribute("disabled", "disabled"); + } + writer.writeAttribute("onClick", "downloadFile('/debug/logdb.sql', 'logdb.sql')"); //: The download button description of the debug interface writer.writeCharacters(tr("Download")); writer.writeEndElement(); // button @@ -289,7 +678,6 @@ QByteArray DebugServerHandler::createDebugXmlDocument() writer.writeEndElement(); // div download-row - // Download row writer.writeStartElement("div"); writer.writeAttribute("class", "download-row"); @@ -309,16 +697,28 @@ QByteArray DebugServerHandler::createDebugXmlDocument() writer.writeAttribute("class", "download-button-column"); writer.writeStartElement("form"); writer.writeAttribute("class", "download-button"); - writer.writeAttribute("method", "get"); - writer.writeAttribute("action", "/debug/syslog"); writer.writeStartElement("button"); writer.writeAttribute("class", "button"); - writer.writeAttribute("type", "submit"); + writer.writeAttribute("type", "button"); + writer.writeAttribute("onClick", "downloadFile('/debug/syslog', 'syslog.log')"); writer.writeCharacters(tr("Download")); writer.writeEndElement(); // button writer.writeEndElement(); // form writer.writeEndElement(); // div download-button-column + writer.writeStartElement("div"); + writer.writeAttribute("class", "show-button-column"); + writer.writeStartElement("form"); + writer.writeAttribute("class", "show-button"); + writer.writeStartElement("button"); + writer.writeAttribute("class", "button"); + writer.writeAttribute("type", "button"); + writer.writeAttribute("onClick", "window.open('/debug/syslog', '_blank')"); + writer.writeCharacters(tr("Show")); + writer.writeEndElement(); // button + writer.writeEndElement(); // form + writer.writeEndElement(); // div show-button-column + writer.writeEndElement(); // div download-row @@ -347,16 +747,34 @@ QByteArray DebugServerHandler::createDebugXmlDocument() writer.writeAttribute("class", "download-button-column"); writer.writeStartElement("form"); writer.writeAttribute("class", "download-button"); - writer.writeAttribute("method", "get"); - writer.writeAttribute("action", "/debug/settings/nymead"); writer.writeStartElement("button"); writer.writeAttribute("class", "button"); - writer.writeAttribute("type", "submit"); + writer.writeAttribute("type", "button"); + if (!QFile::exists(NymeaSettings(NymeaSettings::SettingsRoleGlobal).fileName())) { + writer.writeAttribute("disabled", "disabled"); + } + writer.writeAttribute("onClick", "downloadFile('/debug/settings/nymead', 'nymead.conf')"); writer.writeCharacters(tr("Download")); writer.writeEndElement(); // button writer.writeEndElement(); // form writer.writeEndElement(); // div download-button-column + writer.writeStartElement("div"); + writer.writeAttribute("class", "show-button-column"); + writer.writeStartElement("form"); + writer.writeAttribute("class", "show-button"); + writer.writeStartElement("button"); + writer.writeAttribute("class", "button"); + writer.writeAttribute("type", "button"); + if (!QFile::exists(NymeaSettings(NymeaSettings::SettingsRoleGlobal).fileName())) { + writer.writeAttribute("disabled", "disabled"); + } + writer.writeAttribute("onClick", "window.open('/debug/settings/nymead', '_blank')"); + writer.writeCharacters(tr("Show")); + writer.writeEndElement(); // button + writer.writeEndElement(); // form + writer.writeEndElement(); // div show-button-column + writer.writeEndElement(); // div download-row @@ -379,16 +797,34 @@ QByteArray DebugServerHandler::createDebugXmlDocument() writer.writeAttribute("class", "download-button-column"); writer.writeStartElement("form"); writer.writeAttribute("class", "download-button"); - writer.writeAttribute("method", "get"); - writer.writeAttribute("action", "/debug/settings/devices"); writer.writeStartElement("button"); writer.writeAttribute("class", "button"); - writer.writeAttribute("type", "submit"); + writer.writeAttribute("type", "button"); + if (!QFile::exists(NymeaSettings(NymeaSettings::SettingsRoleDevices).fileName())) { + writer.writeAttribute("disabled", "disabled"); + } + writer.writeAttribute("onClick", "downloadFile('/debug/settings/devices', 'devices.conf')"); writer.writeCharacters(tr("Download")); writer.writeEndElement(); // button writer.writeEndElement(); // form writer.writeEndElement(); // div download-button-column + writer.writeStartElement("div"); + writer.writeAttribute("class", "show-button-column"); + writer.writeStartElement("form"); + writer.writeAttribute("class", "show-button"); + writer.writeStartElement("button"); + writer.writeAttribute("class", "button"); + writer.writeAttribute("type", "button"); + if (!QFile::exists(NymeaSettings(NymeaSettings::SettingsRoleDevices).fileName())) { + writer.writeAttribute("disabled", "true"); + } + writer.writeAttribute("onClick", "window.open('/debug/settings/devices', '_blank')"); + writer.writeCharacters(tr("Show")); + writer.writeEndElement(); // button + writer.writeEndElement(); // form + writer.writeEndElement(); // div show-button-column + writer.writeEndElement(); // div download-row @@ -411,16 +847,34 @@ QByteArray DebugServerHandler::createDebugXmlDocument() writer.writeAttribute("class", "download-button-column"); writer.writeStartElement("form"); writer.writeAttribute("class", "download-button"); - writer.writeAttribute("method", "get"); - writer.writeAttribute("action", "/debug/settings/devicestates"); writer.writeStartElement("button"); writer.writeAttribute("class", "button"); - writer.writeAttribute("type", "submit"); + writer.writeAttribute("type", "button"); + if (!QFile::exists(NymeaSettings(NymeaSettings::SettingsRoleDeviceStates).fileName())) { + writer.writeAttribute("disabled", "true"); + } + writer.writeAttribute("onClick", "downloadFile('/debug/settings/devicestates', 'devicestates.conf')"); writer.writeCharacters(tr("Download")); writer.writeEndElement(); // button writer.writeEndElement(); // form writer.writeEndElement(); // div download-button-column + writer.writeStartElement("div"); + writer.writeAttribute("class", "show-button-column"); + writer.writeStartElement("form"); + writer.writeAttribute("class", "show-button"); + writer.writeStartElement("button"); + writer.writeAttribute("class", "button"); + writer.writeAttribute("type", "button"); + if (!QFile::exists(NymeaSettings(NymeaSettings::SettingsRoleDeviceStates).fileName())) { + writer.writeAttribute("disabled", "true"); + } + writer.writeAttribute("onClick", "window.open('/debug/settings/devicestates', '_blank')"); + writer.writeCharacters(tr("Show")); + writer.writeEndElement(); // button + writer.writeEndElement(); // form + writer.writeEndElement(); // div show-button-column + writer.writeEndElement(); // div download-row @@ -443,16 +897,34 @@ QByteArray DebugServerHandler::createDebugXmlDocument() writer.writeAttribute("class", "download-button-column"); writer.writeStartElement("form"); writer.writeAttribute("class", "download-button"); - writer.writeAttribute("method", "get"); - writer.writeAttribute("action", "/debug/settings/rules"); writer.writeStartElement("button"); writer.writeAttribute("class", "button"); - writer.writeAttribute("type", "submit"); + writer.writeAttribute("type", "button"); + if (!QFile::exists(NymeaSettings(NymeaSettings::SettingsRoleRules).fileName())) { + writer.writeAttribute("disabled", "true"); + } + writer.writeAttribute("onClick", "downloadFile('/debug/settings/rules', 'rules.conf')"); writer.writeCharacters(tr("Download")); writer.writeEndElement(); // button writer.writeEndElement(); // form writer.writeEndElement(); // div download-button-column + writer.writeStartElement("div"); + writer.writeAttribute("class", "show-button-column"); + writer.writeStartElement("form"); + writer.writeAttribute("class", "show-button"); + writer.writeStartElement("button"); + writer.writeAttribute("class", "button"); + writer.writeAttribute("type", "button"); + if (!QFile::exists(NymeaSettings(NymeaSettings::SettingsRoleRules).fileName())) { + writer.writeAttribute("disabled", "true"); + } + writer.writeAttribute("onClick", "window.open('/debug/settings/rules', '_blank')"); + writer.writeCharacters(tr("Show")); + writer.writeEndElement(); // button + writer.writeEndElement(); // form + writer.writeEndElement(); // div show-button-column + writer.writeEndElement(); // div download-row @@ -475,20 +947,168 @@ QByteArray DebugServerHandler::createDebugXmlDocument() writer.writeAttribute("class", "download-button-column"); writer.writeStartElement("form"); writer.writeAttribute("class", "download-button"); - writer.writeAttribute("method", "get"); - writer.writeAttribute("action", "/debug/settings/plugins"); writer.writeStartElement("button"); writer.writeAttribute("class", "button"); - writer.writeAttribute("type", "submit"); + writer.writeAttribute("type", "button"); + if (!QFile::exists(NymeaSettings(NymeaSettings::SettingsRolePlugins).fileName())) { + writer.writeAttribute("disabled", "true"); + } + writer.writeAttribute("onClick", "downloadFile('/debug/settings/plugins', 'plugins.conf')"); writer.writeCharacters(tr("Download")); writer.writeEndElement(); // button writer.writeEndElement(); // form writer.writeEndElement(); // div download-button-column + writer.writeStartElement("div"); + writer.writeAttribute("class", "show-button-column"); + writer.writeStartElement("form"); + writer.writeAttribute("class", "show-button"); + writer.writeStartElement("button"); + writer.writeAttribute("class", "button"); + writer.writeAttribute("type", "button"); + if (!QFile::exists(NymeaSettings(NymeaSettings::SettingsRolePlugins).fileName())) { + writer.writeAttribute("disabled", "true"); + } + writer.writeAttribute("onClick", "window.open('/debug/settings/plugins', '_blank')"); + writer.writeCharacters(tr("Show")); + writer.writeEndElement(); // button + writer.writeEndElement(); // form + writer.writeEndElement(); // div show-button-column + writer.writeEndElement(); // div download-row - writer.writeEndElement(); // div body + // Network section + writer.writeStartElement("div"); + writer.writeAttribute("class", "network"); + writer.writeEmptyElement("hr"); + //: The network section of the debug interface + writer.writeTextElement("h2", tr("Network")); + + //: The network section description of the debug interface + writer.writeTextElement("p", tr("This section allows you to perform different network connectivity tests in order " + "to find out if the device nymea is running on is online and has full network connectivity.")); + + + // Ping section + writer.writeEmptyElement("hr"); + //: The ping section of the debug interface + writer.writeTextElement("h3", tr("Ping nymea.io")); + writer.writeEmptyElement("hr"); + + // Start ping button + writer.writeStartElement("button"); + writer.writeAttribute("class", "button"); + writer.writeAttribute("type", "button"); + writer.writeAttribute("id", "pingButton"); + writer.writeAttribute("onClick", "startPingTest()"); + //: The ping button text of the debug interface + writer.writeCharacters(tr("Start ping test")); + writer.writeEndElement(); // button + + // Ping output + writer.writeStartElement("textarea"); + writer.writeAttribute("class", "console-textarea"); + writer.writeAttribute("id", "pingTextArea"); + writer.writeAttribute("readonly", "readonly"); + writer.writeAttribute("rows", "12"); + writer.writeCharacters(""); + writer.writeEndElement(); // textarea + + + // Dig section + writer.writeEmptyElement("hr"); + //: The ping section of the debug interface + writer.writeTextElement("h3", tr("DNS lookup for nymea.io")); + writer.writeEmptyElement("hr"); + + // Start dig button + writer.writeStartElement("button"); + writer.writeAttribute("class", "button"); + writer.writeAttribute("type", "button"); + writer.writeAttribute("id", "digButton"); + writer.writeAttribute("onClick", "startDigTest()"); + //: The ping button text of the debug interface + writer.writeCharacters(tr("Start DNS lookup test")); + writer.writeEndElement(); // button + + // Dig output + writer.writeStartElement("textarea"); + writer.writeAttribute("class", "console-textarea"); + writer.writeAttribute("id", "digTextArea"); + writer.writeAttribute("readonly", "readonly"); + writer.writeAttribute("rows", "21"); + writer.writeCharacters(""); + writer.writeEndElement(); // textarea + + // Dig section + writer.writeEmptyElement("hr"); + //: The ping section of the debug interface + writer.writeTextElement("h3", tr("Trace path nymea.io")); + writer.writeEmptyElement("hr"); + + // Start tracepath button + writer.writeStartElement("button"); + writer.writeAttribute("class", "button"); + writer.writeAttribute("type", "button"); + writer.writeAttribute("id", "tracePathButton"); + writer.writeAttribute("onClick", "startTracePathTest()"); + //: The ping button text of the debug interface + writer.writeCharacters(tr("Start trace path test")); + writer.writeEndElement(); // button + + // Dig output + writer.writeStartElement("textarea"); + writer.writeAttribute("class", "console-textarea"); + writer.writeAttribute("id", "tracePathTextArea"); + writer.writeAttribute("readonly", "readonly"); + writer.writeAttribute("rows", "20"); + writer.writeCharacters(""); + writer.writeEndElement(); // textarea + + writer.writeEndElement(); // div network + + // Logs stream + writer.writeStartElement("div"); + writer.writeAttribute("class", "logstream"); + writer.writeEmptyElement("hr"); + //: The network section of the debug interface + writer.writeTextElement("h2", tr("Server debug log stream")); + writer.writeEmptyElement("hr"); + + // Start stream button + writer.writeStartElement("button"); + writer.writeAttribute("class", "button"); + writer.writeAttribute("type", "button"); + writer.writeAttribute("id", "connectWebsocketButton"); + writer.writeAttribute("onClick", "connectWebsocket()"); + //: The connect button for the log stream of the debug interface + writer.writeCharacters(tr("Connect stream")); + writer.writeEndElement(); // button + + // Stop stream button + writer.writeStartElement("button"); + writer.writeAttribute("class", "button"); + writer.writeAttribute("type", "button"); + writer.writeAttribute("id", "disconnectWebsocketButton"); + writer.writeAttribute("onClick", "disconnectWebsocket()"); + writer.writeAttribute("disabled", "true"); + //: The disconnect button for the log stream of the debug interface + writer.writeCharacters(tr("Disconnect stream")); + writer.writeEndElement(); // button + + + // Dig output + writer.writeStartElement("textarea"); + writer.writeAttribute("class", "console-textarea"); + writer.writeAttribute("id", "logsTextArea"); + writer.writeAttribute("readonly", "readonly"); + writer.writeAttribute("rows", "30"); + writer.writeCharacters(""); + writer.writeEndElement(); // textarea + + + writer.writeEndElement(); // div body // Footer writer.writeStartElement("div"); @@ -573,290 +1193,120 @@ QByteArray DebugServerHandler::createErrorXmlDocument(HttpReply::HttpStatusCode writer.writeEndElement(); // div footer writer.writeEndElement(); // div container - writer.writeEndElement(); // html return data; } -QByteArray DebugServerHandler::loadResourceFile(const QString &resourceFileName) +void consoleLogHandler(QtMsgType type, const QMessageLogContext& context, const QString& message) { - QFile resourceFile(QString(":%1").arg(resourceFileName)); - if (!resourceFile.open(QFile::ReadOnly | QFile::Text)) { - qCWarning(dcWebServer()) << "Could not open resource file" << resourceFile.fileName(); - return QByteArray(); + QString messageString; + QString timeString = QDateTime::currentDateTime().toString("yyyy.MM.dd hh:mm:ss.zzz"); + switch (type) { + case QtInfoMsg: + messageString = QString(" I %1 | %2: %3").arg(timeString).arg(context.category).arg(message); + fprintf(stdout, " I | %s: %s\n", context.category, message.toUtf8().data()); + break; + case QtDebugMsg: + messageString = QString(" I %1 | %2: %3").arg(timeString).arg(context.category).arg(message); + fprintf(stdout, " I | %s: %s\n", context.category, message.toUtf8().data()); + break; + case QtWarningMsg: + messageString = QString(" W %1 | %2: %3").arg(timeString).arg(context.category).arg(message); + fprintf(stderr, " W | %s: %s\n", context.category, message.toUtf8().data()); + break; + case QtCriticalMsg: + messageString = QString(" C %1 | %2: %3").arg(timeString).arg(context.category).arg(message); + fprintf(stderr, " C | %s: %s\n", context.category, message.toUtf8().data()); + break; + case QtFatalMsg: + messageString = QString(" F %1 | %2: %3").arg(timeString).arg(context.category).arg(message); + fprintf(stderr, " F | %s: %s\n", context.category, message.toUtf8().data()); + break; } + fflush(stdout); + fflush(stderr); - QTextStream inputStream(&resourceFile); - return inputStream.readAll().toUtf8(); + foreach (QWebSocket *client, DebugServerHandler::s_websocketClients) { + client->sendTextMessage(messageString + "\r\n"); + } } -QString DebugServerHandler::getResourceFileName(const QString &requestPath) +void DebugServerHandler::onTimeout() { - return QString(requestPath).remove("/debug"); + foreach (QWebSocket *client, DebugServerHandler::s_websocketClients) { + client->sendTextMessage("Hallo!\n"); + } } -bool DebugServerHandler::resourceFileExits(const QString &requestPath) +void DebugServerHandler::onWebsocketClientConnected() { - QFile resourceFile(QString(":%1").arg(getResourceFileName(requestPath))); - return resourceFile.exists(); + QWebSocket *client = m_websocketServer->nextPendingConnection(); + DebugServerHandler::s_websocketClients.append(client); + qCDebug(dcWebServer()) << "DebugServer: New websocket client connected:" << client->peerAddress().toString(); + + connect(client, SIGNAL(error(QAbstractSocket::SocketError)), this, SLOT(onWebsocketClientError(QAbstractSocket::SocketError))); + connect(client, &QWebSocket::disconnected, this, &DebugServerHandler::onWebsocketClientDisconnected); } -HttpReply *DebugServerHandler::processDebugFileRequest(const QString &requestPath) +void DebugServerHandler::onWebsocketClientDisconnected() { - // Here we already know that the resource file exists - QString resourceFileName = getResourceFileName(requestPath); - QByteArray data = loadResourceFile(resourceFileName); - - // Create reply for resource file - HttpReply *reply = RestResource::createSuccessReply(); - reply->setPayload(data); - - // Check content type - if (resourceFileName.endsWith(".css")) { - reply->setHeader(HttpReply::ContentTypeHeader, "text/css; charset=\"utf-8\";"); - } else if (resourceFileName.endsWith(".svg")) { - reply->setHeader(HttpReply::ContentTypeHeader, "image/svg+xml; charset=\"utf-8\";"); - } - - return reply; + QWebSocket *client = static_cast(sender()); + qCDebug(dcWebServer()) << "DebugServer: Websocket client disconnected" << client->peerAddress().toString(); + DebugServerHandler::s_websocketClients.removeAll(client); + client->deleteLater(); } - -HttpReply *DebugServerHandler::processDebugRequest(const QString &requestPath) +void DebugServerHandler::onWebsocketClientError(QAbstractSocket::SocketError error) { - qCDebug(dcWebServer()) << "Debug request for" << requestPath; - - // Check if debug page request - if (requestPath == "/debug" || requestPath == "/debug/") { - qCDebug(dcWebServer()) << "Create debug interface page"; - // Fallback default debug page - HttpReply *reply = RestResource::createSuccessReply(); - reply->setHeader(HttpReply::ContentTypeHeader, "text/html"); - reply->setPayload(createDebugXmlDocument()); - return reply; - } - - // Check if this is a logdb requested - if (requestPath.startsWith("/debug/logdb.sql")) { - qCDebug(dcWebServer()) << "Loading" << NymeaCore::instance()->configuration()->logDBName(); - QFile logDatabaseFile(NymeaCore::instance()->configuration()->logDBName()); - if (!logDatabaseFile.exists()) { - qCWarning(dcWebServer()) << "Could not read log database file for debug download" << NymeaCore::instance()->configuration()->logDBName() << "file does not exist."; - HttpReply *reply = RestResource::createErrorReply(HttpReply::NotFound); - reply->setHeader(HttpReply::ContentTypeHeader, "text/html"); - //: The HTTP error message of the debug interface. The %1 represents the file name. - reply->setPayload(createErrorXmlDocument(HttpReply::NotFound, tr("Could not find file \"%1\".").arg(logDatabaseFile.fileName()))); - return reply; - } - - if (!logDatabaseFile.open(QFile::ReadOnly)) { - qCWarning(dcWebServer()) << "Could not read log database file for debug download" << NymeaCore::instance()->configuration()->logDBName(); - HttpReply *reply = RestResource::createErrorReply(HttpReply::Forbidden); - reply->setHeader(HttpReply::ContentTypeHeader, "text/html"); - //: The HTTP error message of the debug interface. The %1 represents the file name. - reply->setPayload(createErrorXmlDocument(HttpReply::NotFound, tr("Could not open file \"%1\".").arg(logDatabaseFile.fileName()))); - return reply; - } - - QByteArray logDatabaseRawData = logDatabaseFile.readAll(); - logDatabaseFile.close(); - - HttpReply *reply = RestResource::createSuccessReply(); - reply->setHeader(HttpReply::ContentTypeHeader, "application/sql"); - reply->setPayload(logDatabaseRawData); - return reply; - } - - - // Check if this is a syslog requested - if (requestPath.startsWith("/debug/syslog")) { - QString syslogFileName = "/var/log/syslog"; - qCDebug(dcWebServer()) << "Loading" << syslogFileName; - QFile syslogFile(syslogFileName); - if (!syslogFile.exists()) { - qCWarning(dcWebServer()) << "Could not read log database file for debug download" << syslogFileName << "file does not exist."; - HttpReply *reply = RestResource::createErrorReply(HttpReply::NotFound); - reply->setHeader(HttpReply::ContentTypeHeader, "text/html"); - reply->setPayload(createErrorXmlDocument(HttpReply::NotFound, tr("Could not find file \"%1\".").arg(syslogFileName))); - return reply; - } - - if (!syslogFile.open(QFile::ReadOnly)) { - qCWarning(dcWebServer()) << "Could not read syslog file for debug download" << syslogFileName; - HttpReply *reply = RestResource::createErrorReply(HttpReply::Forbidden); - reply->setHeader(HttpReply::ContentTypeHeader, "text/html"); - reply->setPayload(createErrorXmlDocument(HttpReply::NotFound, tr("Could not open file \"%1\".").arg(syslogFileName))); - return reply; - } - - QByteArray syslogFileData = syslogFile.readAll(); - syslogFile.close(); - - HttpReply *reply = RestResource::createSuccessReply(); - reply->setHeader(HttpReply::ContentTypeHeader, "text/plain"); - reply->setPayload(syslogFileData); - return reply; - } - - // Check if this is a settings request - if (requestPath.startsWith("/debug/settings")) { - if (requestPath.startsWith("/debug/settings/devices")) { - QString settingsFileName = NymeaSettings(NymeaSettings::SettingsRoleDevices).fileName(); - qCDebug(dcWebServer()) << "Loading" << settingsFileName; - QFile settingsFile(settingsFileName); - if (!settingsFile.exists()) { - qCWarning(dcWebServer()) << "Could not read file for debug download" << settingsFileName << "file does not exist."; - HttpReply *reply = RestResource::createErrorReply(HttpReply::NotFound); - reply->setHeader(HttpReply::ContentTypeHeader, "text/html"); - reply->setPayload(createErrorXmlDocument(HttpReply::NotFound, tr("Could not find file \"%1\".").arg(settingsFileName))); - return reply; - } - - if (!settingsFile.open(QFile::ReadOnly)) { - qCWarning(dcWebServer()) << "Could not read file for debug download" << settingsFileName; - HttpReply *reply = RestResource::createErrorReply(HttpReply::Forbidden); - reply->setHeader(HttpReply::ContentTypeHeader, "text/html"); - reply->setPayload(createErrorXmlDocument(HttpReply::NotFound, tr("Could not open file \"%1\".").arg(settingsFileName))); - return reply; - } - - QByteArray settingsFileData = settingsFile.readAll(); - settingsFile.close(); - - HttpReply *reply = RestResource::createSuccessReply(); - reply->setHeader(HttpReply::ContentTypeHeader, "text/plain"); - reply->setPayload(settingsFileData); - return reply; - } - - if (requestPath.startsWith("/debug/settings/rules")) { - QString settingsFileName = NymeaSettings(NymeaSettings::SettingsRoleRules).fileName(); - qCDebug(dcWebServer()) << "Loading" << settingsFileName; - QFile settingsFile(settingsFileName); - if (!settingsFile.exists()) { - qCWarning(dcWebServer()) << "Could not read file for debug download" << settingsFileName << "file does not exist."; - HttpReply *reply = RestResource::createErrorReply(HttpReply::NotFound); - reply->setHeader(HttpReply::ContentTypeHeader, "text/html"); - reply->setPayload(createErrorXmlDocument(HttpReply::NotFound, tr("Could not find file \"%1\".").arg(settingsFileName))); - return reply; - } - - if (!settingsFile.open(QFile::ReadOnly)) { - qCWarning(dcWebServer()) << "Could not read file for debug download" << settingsFileName; - HttpReply *reply = RestResource::createErrorReply(HttpReply::Forbidden); - reply->setHeader(HttpReply::ContentTypeHeader, "text/html"); - reply->setPayload(createErrorXmlDocument(HttpReply::NotFound, tr("Could not open file \"%1\".").arg(settingsFileName))); - return reply; - } - - QByteArray settingsFileData = settingsFile.readAll(); - settingsFile.close(); - - HttpReply *reply = RestResource::createSuccessReply(); - reply->setHeader(HttpReply::ContentTypeHeader, "text/plain"); - reply->setPayload(settingsFileData); - return reply; - } - - if (requestPath.startsWith("/debug/settings/nymead")) { - QString settingsFileName = NymeaSettings(NymeaSettings::SettingsRoleGlobal).fileName(); - qCDebug(dcWebServer()) << "Loading" << settingsFileName; - QFile settingsFile(settingsFileName); - if (!settingsFile.exists()) { - qCWarning(dcWebServer()) << "Could not read file for debug download" << settingsFileName << "file does not exist."; - HttpReply *reply = RestResource::createErrorReply(HttpReply::NotFound); - reply->setHeader(HttpReply::ContentTypeHeader, "text/html"); - reply->setPayload(createErrorXmlDocument(HttpReply::NotFound, tr("Could not find file \"%1\".").arg(settingsFileName))); - return reply; - } - - if (!settingsFile.open(QFile::ReadOnly)) { - qCWarning(dcWebServer()) << "Could not read file for debug download" << settingsFileName; - HttpReply *reply = RestResource::createErrorReply(HttpReply::Forbidden); - reply->setHeader(HttpReply::ContentTypeHeader, "text/html"); - reply->setPayload(createErrorXmlDocument(HttpReply::NotFound, tr("Could not open file \"%1\".").arg(settingsFileName))); - return reply; - } - - QByteArray settingsFileData = settingsFile.readAll(); - settingsFile.close(); - - HttpReply *reply = RestResource::createSuccessReply(); - reply->setHeader(HttpReply::ContentTypeHeader, "text/plain"); - reply->setPayload(settingsFileData); - return reply; - } - - if (requestPath.startsWith("/debug/settings/devicestates")) { - QString settingsFileName = NymeaSettings(NymeaSettings::SettingsRoleDeviceStates).fileName(); - qCDebug(dcWebServer()) << "Loading" << settingsFileName; - QFile settingsFile(settingsFileName); - if (!settingsFile.exists()) { - qCWarning(dcWebServer()) << "Could not read file for debug download" << settingsFileName << "file does not exist."; - HttpReply *reply = RestResource::createErrorReply(HttpReply::NotFound); - reply->setHeader(HttpReply::ContentTypeHeader, "text/html"); - reply->setPayload(createErrorXmlDocument(HttpReply::NotFound, tr("Could not find file \"%1\".").arg(settingsFileName))); - return reply; - } - - if (!settingsFile.open(QFile::ReadOnly)) { - qCWarning(dcWebServer()) << "Could not read file for debug download" << settingsFileName; - HttpReply *reply = RestResource::createErrorReply(HttpReply::Forbidden); - reply->setHeader(HttpReply::ContentTypeHeader, "text/html"); - reply->setPayload(createErrorXmlDocument(HttpReply::NotFound, tr("Could not open file \"%1\".").arg(settingsFileName))); - return reply; - } - - QByteArray settingsFileData = settingsFile.readAll(); - settingsFile.close(); - - HttpReply *reply = RestResource::createSuccessReply(); - reply->setHeader(HttpReply::ContentTypeHeader, "text/plain"); - reply->setPayload(settingsFileData); - return reply; - } - - if (requestPath.startsWith("/debug/settings/plugins")) { - QString settingsFileName = NymeaSettings(NymeaSettings::SettingsRolePlugins).fileName(); - qCDebug(dcWebServer()) << "Loading" << settingsFileName; - QFile settingsFile(settingsFileName); - if (!settingsFile.exists()) { - qCWarning(dcWebServer()) << "Could not read file for debug download" << settingsFileName << "file does not exist."; - HttpReply *reply = RestResource::createErrorReply(HttpReply::NotFound); - reply->setHeader(HttpReply::ContentTypeHeader, "text/html"); - reply->setPayload(createErrorXmlDocument(HttpReply::NotFound, tr("Could not find file \"%1\".").arg(settingsFileName))); - return reply; - } - - if (!settingsFile.open(QFile::ReadOnly)) { - qCWarning(dcWebServer()) << "Could not read file for debug download" << settingsFileName; - HttpReply *reply = RestResource::createErrorReply(HttpReply::Forbidden); - reply->setHeader(HttpReply::ContentTypeHeader, "text/html"); - reply->setPayload(createErrorXmlDocument(HttpReply::NotFound, tr("Could not open file \"%1\".").arg(settingsFileName))); - return reply; - } - - QByteArray settingsFileData = settingsFile.readAll(); - settingsFile.close(); - - HttpReply *reply = RestResource::createSuccessReply(); - reply->setHeader(HttpReply::ContentTypeHeader, "text/plain"); - reply->setPayload(settingsFileData); - return reply; - } - } - - // Check if this is a resource file request - if (resourceFileExits(requestPath)) { - return processDebugFileRequest(requestPath); - } - - // If nothing matches, redirect to /debug page - qCWarning(dcWebServer()) << "Resource for debug interface not found. Redirecting to /debug"; - HttpReply *reply = RestResource::createErrorReply(HttpReply::PermanentRedirect); - reply->setHeader(HttpReply::LocationHeader, "/debug"); - return reply; + QWebSocket *client = static_cast(sender()); + qCWarning(dcWebServer()) << "DebugServer: Websocket client error" << client->peerAddress().toString() << error << client->errorString(); } +void DebugServerHandler::onPingProcessFinished(int exitCode, QProcess::ExitStatus exitStatus) +{ + qCDebug(dcWebServer()) << "DebugServer: Ping process finished" << exitCode << exitStatus; + QByteArray processOutput = m_pingProcess->readAll(); + qCDebug(dcWebServer()) << "DebugServer: Ping output:" << endl << qUtf8Printable(processOutput); + + m_pingReply->setPayload(processOutput); + m_pingReply->setHttpStatusCode(HttpReply::Ok); + m_pingReply->finished(); + m_pingReply = nullptr; + + m_pingProcess->deleteLater(); + m_pingProcess = nullptr; +} + +void DebugServerHandler::onDigProcessFinished(int exitCode, QProcess::ExitStatus exitStatus) +{ + qCDebug(dcWebServer()) << "DebugServer: Dig process finished" << exitCode << exitStatus; + QByteArray processOutput = m_digProcess->readAll(); + qCDebug(dcWebServer()) << "DebugServer: Dig output:" << endl << qUtf8Printable(processOutput); + + m_digReply->setPayload(processOutput); + m_digReply->setHttpStatusCode(HttpReply::Ok); + m_digReply->finished(); + m_digReply = nullptr; + + m_digProcess->deleteLater(); + m_digProcess = nullptr; +} + +void DebugServerHandler::onTracePathProcessFinished(int exitCode, QProcess::ExitStatus exitStatus) +{ + qCDebug(dcWebServer()) << "DebugServer: Tracepath process finished" << exitCode << exitStatus; + QByteArray processOutput = m_tracePathProcess->readAll(); + qCDebug(dcWebServer()) << "DebugServer: Tracepath output:" << endl << qUtf8Printable(processOutput); + + m_tracePathReply->setPayload(processOutput); + m_tracePathReply->setHttpStatusCode(HttpReply::Ok); + m_tracePathReply->finished(); + m_tracePathReply = nullptr; + + m_tracePathProcess->deleteLater(); + m_tracePathProcess = nullptr; +} + + } diff --git a/libnymea-core/debugserverhandler.h b/libnymea-core/debugserverhandler.h index 3de2a46d..8260f493 100644 --- a/libnymea-core/debugserverhandler.h +++ b/libnymea-core/debugserverhandler.h @@ -21,7 +21,10 @@ #ifndef DEBUGSERVERHANDLER_H #define DEBUGSERVERHANDLER_H +#include #include +#include +#include #include "httpreply.h" @@ -35,15 +38,41 @@ public: HttpReply *processDebugRequest(const QString &requestPath); + static QList s_websocketClients; + static void consoleLogHandler(QtMsgType type, const QMessageLogContext& context, const QString& message); + private: - QByteArray createDebugXmlDocument(); - QByteArray createErrorXmlDocument(HttpReply::HttpStatusCode statusCode, const QString &errorMessage); - QByteArray loadResourceFile(const QString &resourceFileName); + QTimer *m_timer = nullptr; + QWebSocketServer *m_websocketServer = nullptr; + + QProcess *m_pingProcess = nullptr; + HttpReply *m_pingReply = nullptr; + + QProcess *m_digProcess = nullptr; + HttpReply *m_digReply = nullptr; + + QProcess *m_tracePathProcess = nullptr; + HttpReply *m_tracePathReply = nullptr; + + QByteArray loadResourceData(const QString &resourceFileName); QString getResourceFileName(const QString &requestPath); bool resourceFileExits(const QString &requestPath); HttpReply *processDebugFileRequest(const QString &requestPath); + QByteArray createDebugXmlDocument(); + QByteArray createErrorXmlDocument(HttpReply::HttpStatusCode statusCode, const QString &errorMessage); + +private slots: + void onTimeout(); + void onWebsocketClientConnected(); + void onWebsocketClientDisconnected(); + void onWebsocketClientError(QAbstractSocket::SocketError error); + + void onPingProcessFinished(int exitCode, QProcess::ExitStatus exitStatus); + void onDigProcessFinished(int exitCode, QProcess::ExitStatus exitStatus); + void onTracePathProcessFinished(int exitCode, QProcess::ExitStatus exitStatus); + }; } diff --git a/libnymea-core/httpreply.cpp b/libnymea-core/httpreply.cpp index 8a9913f4..3635c424 100644 --- a/libnymea-core/httpreply.cpp +++ b/libnymea-core/httpreply.cpp @@ -417,7 +417,7 @@ QByteArray HttpReply::getHeaderType(const HttpReply::HttpHeaderType &headerType) */ void HttpReply::startWait() { - m_timer->start(10000); + m_timer->start(60000); } void HttpReply::timeout() diff --git a/libnymea-core/webserver.cpp b/libnymea-core/webserver.cpp index cce62165..3867a6ad 100644 --- a/libnymea-core/webserver.cpp +++ b/libnymea-core/webserver.cpp @@ -132,7 +132,7 @@ QUrl WebServer::serverUrl() const void WebServer::sendHttpReply(HttpReply *reply) { // get the right socket - QSslSocket *socket = 0; + QSslSocket *socket = nullptr; socket = m_clientList.value(reply->clientId()); if (!socket) { qCWarning(dcWebServer) << "Invalid socket pointer! This should never happen!!! Missing clientId in reply?"; @@ -141,7 +141,7 @@ void WebServer::sendHttpReply(HttpReply *reply) // send raw data reply->packReply(); - qCDebug(dcWebServer) << "respond" << reply->httpStatusCode() << reply->httpReasonPhrase(); + qCDebug(dcWebServer) << "Respond" << reply->httpStatusCode() << reply->httpReasonPhrase(); socket->write(reply->data()); } @@ -161,7 +161,7 @@ bool WebServer::verifyFile(QSslSocket *socket, const QString &fileName) // make sure the file is in the public directory if (!file.canonicalFilePath().startsWith(QDir(m_configuration.publicFolder).canonicalPath())) { - qCWarning(dcWebServer) << "requested file" << file.fileName() << "is outside the public folder."; + qCWarning(dcWebServer) << "Requested file" << file.fileName() << "is outside the public folder."; HttpReply *reply = RestResource::createErrorReply(HttpReply::Forbidden); reply->setClientId(m_clientList.key(socket)); sendHttpReply(reply); @@ -171,7 +171,7 @@ bool WebServer::verifyFile(QSslSocket *socket, const QString &fileName) // make sure we can read the file if (!file.isReadable()) { - qCWarning(dcWebServer) << "requested file" << file.fileName() << "is not readable."; + qCWarning(dcWebServer) << "Requested file" << file.fileName() << "is not readable."; HttpReply *reply = RestResource::createErrorReply(HttpReply::Forbidden); reply->setClientId(m_clientList.key(socket)); reply->setPayload("403 Forbidden. File not readable"); @@ -388,8 +388,15 @@ void WebServer::readClient() HttpReply *reply = NymeaCore::instance()->debugServerHandler()->processDebugRequest(request.url().path()); reply->setClientId(clientId); - sendHttpReply(reply); - reply->deleteLater(); + + // Handle async replies + if (reply->type() == HttpReply::TypeAsync) { + connect(reply, &HttpReply::finished, this, &WebServer::onAsyncReplyFinished); + reply->startWait(); + } else { + sendHttpReply(reply); + reply->deleteLater(); + } return; } else { qCWarning(dcWebServer()) << "The debug server handler is disabled. You can enable it by adding \'debugServerEnabled=true\' in the \'nymead\' section of the nymead.conf file."; @@ -403,7 +410,7 @@ void WebServer::readClient() // Check server.xml call if (request.url().path() == "/server.xml" && request.method() == HttpRequest::Get) { - qCDebug(dcWebServer) << "server XML request call"; + qCDebug(dcWebServer) << "Server XML request call"; HttpReply *reply = RestResource::createSuccessReply(); reply->setHeader(HttpReply::ContentTypeHeader, "text/xml"); reply->setPayload(createServerXmlDocument(socket->localAddress())); @@ -418,7 +425,7 @@ void WebServer::readClient() if (request.method() == HttpRequest::Get) { // Check if the webinterface dir does exist, otherwise a filerequest is not relevant if (!QDir(m_configuration.publicFolder).exists()) { - qCWarning(dcWebServer) << "webinterface folder" << m_configuration.publicFolder << "does not exist."; + qCWarning(dcWebServer) << "Webinterface folder" << m_configuration.publicFolder << "does not exist."; HttpReply *reply = RestResource::createErrorReply(HttpReply::NotFound); reply->setClientId(clientId); sendHttpReply(reply); @@ -432,7 +439,7 @@ void WebServer::readClient() QFile file(path); if (file.open(QFile::ReadOnly | QFile::Truncate)) { - qCDebug(dcWebServer) << "load file" << file.fileName(); + qCDebug(dcWebServer) << "Load file" << file.fileName(); HttpReply *reply = RestResource::createSuccessReply(); // Check content type @@ -522,6 +529,21 @@ void WebServer::onError(QAbstractSocket::SocketError error) qCWarning(dcWebServer()) << QString("Client socket error %1:%2 ->").arg(socket->peerAddress().toString()).arg(socket->peerPort()) << socket->errorString(); } +void WebServer::onAsyncReplyFinished() +{ + HttpReply *reply = qobject_cast(sender()); + qCDebug(dcWebServer) << "Async reply finished"; + + // check if the reply timeouted + if (reply->timedOut()) { + reply->clear(); + reply->setHttpStatusCode(HttpReply::GatewayTimeout); + } + + sendHttpReply(reply); + reply->deleteLater(); +} + void WebServer::onAvahiServiceStateChanged(const QtAvahiService::QtAvahiServiceState &state) { Q_UNUSED(state) @@ -826,7 +848,7 @@ void WebServerClient::removeConnection(QSslSocket *socket) */ void WebServerClient::resetTimout(QSslSocket *socket) { - QTimer *timer = 0; + QTimer *timer = nullptr; timer = m_runningConnections.key(socket); if (timer) timer->start(); diff --git a/libnymea-core/webserver.h b/libnymea-core/webserver.h index 894a5bf8..1d9a31e8 100644 --- a/libnymea-core/webserver.h +++ b/libnymea-core/webserver.h @@ -113,6 +113,7 @@ private slots: void onDisconnected(); void onEncrypted(); void onError(QAbstractSocket::SocketError error); + void onAsyncReplyFinished(); void onAvahiServiceStateChanged(const QtAvahiService::QtAvahiServiceState &state); void resetAvahiService();