From 7f2dd35059eb0ef3fcee61058b233f121ec0ba7e Mon Sep 17 00:00:00 2001 From: nuxsmin Date: Mon, 15 Oct 2018 02:56:00 +0200 Subject: [PATCH] * [MOD] Improved plugins management * [MOD] Code refactoring Signed-off-by: nuxsmin --- app/locales/en_GB/LC_MESSAGES/messages.mo | Bin 105050 -> 105315 bytes app/locales/en_GB/LC_MESSAGES/messages.po | 375 +++++++++--------- app/locales/en_US/LC_MESSAGES/messages.mo | Bin 105050 -> 105315 bytes app/locales/en_US/LC_MESSAGES/messages.po | 375 +++++++++--------- .../web/Controllers/BootstrapController.php | 8 + .../web/Controllers/ControllerBase.php | 48 ++- .../web/Controllers/Helpers/LayoutHelper.php | 4 +- .../web/Controllers/IndexController.php | 4 +- .../web/Controllers/LoginController.php | 81 ++-- .../web/Controllers/PluginController.php | 7 + .../web/Controllers/ResourceController.php | 2 + .../web/Controllers/StatusController.php | 8 +- .../Controllers/Traits/WebControllerTrait.php | 34 ++ .../Controllers/UserPassResetController.php | 3 + .../UserSettingsManagerController.php | 37 +- app/modules/web/Init.php | 5 +- composer.json | 5 +- lib/SP/Bootstrap.php | 23 ++ lib/SP/Core/Context/ContextInterface.php | 17 + lib/SP/Core/Context/SessionContext.php | 37 +- lib/SP/Core/Context/StatelessContext.php | 33 ++ lib/SP/Core/Events/Event.php | 17 +- lib/SP/Core/Events/EventDispatcherBase.php | 14 +- lib/SP/Html/Minify.php | 2 +- lib/SP/Http/Request.php | 5 +- lib/SP/Mvc/Controller/ControllerTrait.php | 20 +- .../ExtensibleControllerInterface.php | 52 +++ .../ExtensibleTabControllerInterface.php | 40 ++ lib/SP/Mvc/View/Template.php | 10 +- lib/SP/Plugin/PluginBase.php | 55 ++- lib/SP/Plugin/PluginEventReceiver.php | 5 +- lib/SP/Plugin/PluginInterface.php | 6 +- lib/SP/Plugin/PluginManager.php | 336 ++++++++++------ lib/SP/Providers/Log/DatabaseLogHandler.php | 3 + lib/SP/Providers/Log/LogInterface.php | 3 +- lib/SP/Services/Auth/LoginService.php | 3 +- lib/SP/Util/ErrorUtil.php | 76 ++-- lib/SP/Util/Util.php | 61 +-- public/js/app-actions.js | 27 +- public/js/app-actions.min.js | 23 +- public/js/app-main.js | 10 +- public/js/app-main.min.js | 4 +- public/js/app-triggers.js | 8 +- public/js/app-triggers.min.js | 28 +- public/js/app.js | 2 +- public/js/app.min.js | 2 +- tests/res/config/config.xml | 8 +- 47 files changed, 1245 insertions(+), 681 deletions(-) create mode 100644 lib/SP/Mvc/Controller/ExtensibleControllerInterface.php create mode 100644 lib/SP/Mvc/Controller/ExtensibleTabControllerInterface.php diff --git a/app/locales/en_GB/LC_MESSAGES/messages.mo b/app/locales/en_GB/LC_MESSAGES/messages.mo index d94f33fc3646deac18bc31bbe8c22095bd14140b..995903bdcb49ae7361c8e459a1e25c263d35befc 100644 GIT binary patch delta 30339 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 delta 30070 zcmZAA1$0$czpn8eT!RLe0D<5hB)CIycb8(t-BxiZr4)CU;;tW72vV%Ll;Tzj6t@C} z^SpchGcMzGS1ms8pY? zbRVCu3YNhjoPddOF;dL86;t9KOn{d#2|lp=515E}l)kQhQdE9+q`v1XNgyE!6)`n7 z#H!dE)zN+o!gH7wA7V0$(a+}#!L%5PWibL~94liLGe1pl**Ixtne7@ua zQVR6jE@ zIj%xa1rHENiWjjKK0-BIY>;cX0j4BA7&VaT7>FxSE3*wXpu?yc|A{Jh2i4Il%a1$Q ztwaV?e&}GZib zN3~Z0RjwhbpAHu9<5|K;)Tx||YG|dU??hERf*Scn)Qa4({C8&bVJ<%jYM{Xu&xfjC z(&E)IKk+7*3%!X1!U*g}U8fhQ>y(U@QM@FofwmYMd!ahe%IWM(M6J+bjEY-PTeTDQ zeK>=f@fA#g4^R{Qf^4DZOYps0q9D`^Ls10^qB?9tr%)^N zC#tQk5jZ(&A^GSbZ~ zGpc?`%!W0v01m(`xE6KG&ZAc1AM`Y$7^B?G)1e9!L!E*8sQjU*5l=_$=`X0Q*??M^ z2+Kcb-ZS5#CK7A3E1wRvb@?q`Y&7eyrLIXrKCF-WVvR-Z?NrpETYwtaN^F1!Q8P$6 z#^>vf`7s!mpxTK*&HN1(!fa#RZ$m2#CO!)D;_|Vqe_;ZbNYI`Jj`R7r0KS~44%eV& zco?c?0FWB+7JXx2x~q$8^Q5Y$X2TYM9$qa&ylxnl9Zu`2P8_zhN?FM#F`e2$x}O+>QzHS4%&O@rd6=P4GEt zivy>y{yI!K2xzIxV|;9Cc0yI`kLqxg#b;Uma@5vs!Nj-+bxTg8ZqEx0!?;u3H7tX9 zi4Q>avuY~)uaWE^ArW3cE$stLhaXV`NHxt3FcgyzFNxa2I;b<#1e0QGRQZ0W>opS9 z?gC5Sh)Id>MNRnJG}b?mz~3ZjMDHyl#&oyTX;BU4LRAb$m8*$b;^wIO-B9I*VqE+I z)xiu@`E{s)?nbTHLDW{A@Cf84a1qr(v>EOTl@hg-;n)hBp$^+#OorDn2w!7%j5Cv~ zhhZ3slQ0|ZK(%`tL+~wX#Z%961MrFv(1^;SW>gi`K{M3MdZQ|gKrQ`3RJkpv>vqVz zfGLRILoNA#W`fzSoeZcmk{8u}Ii$YlYhnqVt-x?p2h&gkSdLo4t*C|%qB_2S`S2d< zgOhBI%TI$UpBuFj#W5AO!=mURe;)dFVN3e=h0S#prlUTgOHm!IM=jy6sJ(lH8qf>W z0DSXYy@aTlrL%ZG)C5YQmcEwdx3}~GsKYxR{lEW{t-w+YCSyD5o?b?6%^TDJKBHz9 zeZKpkBth+cOVn-o0n^|r%!5ZT7~f)AOuoRKfiP70Cg^Et1`<%kX{bZD$>QfRGx6sb zhRGJX4y$1<;{7o-F2`UzfGP0~=D<%_2(vEY&pB*~S#TPv-0nrJzY1O?K?4X_?Ea!j zhg$kF7Vm-?i2sC{a3kulUBLAC4{C<-m$(7vKy^?XlVcZD`H`sd^DKYQ63;b!iG%`V zyhmNDoJ(EBvZ#iepawVq)zEa*;aiVt@D{3`Z<#yY$xwTr3v*&w)P%aDR(v+9y{#UB ztOU+l!Urpme7RfN{Fssa8mJ0AQ3Lo1)zB}fEjVcL8>sKezo>y_UE#K-GOAoBRC}W_ z19~e7Xokm8BYlV=81#!fB;lxz8>6nR=zm565(rYlNC;e@kD4 zOvLl;BcQ#y>=Jx0P^Lx}xXP{8mh6`PD|Zv!T$f8SXG>iBO|Ls8c`v!fcUZFWR0rH49P3osXML9N(rjF10fFveW( z4s}*kelv`TeNfkN2znafCITh#Hpa!^4X&e{r~y<(o%S}U8B9YpxEagfamXx9hcO57*O(K7H?jU&!s?scA?t|RTo6A>uybP%uBohropl39~i2=2uzJPEdBv?eS`MtXP*5pN2q$Dj`B4AhL*TKcb;koXzYfNz`6F%j`EsFh5#-}RFM{lEVi31}}1 zDgoP>{V)abai|U#qn30BYAa5n26zFrGPkh=zPJ2Bzq)cIQTY{7E7}}&R{EkBi@*i~ zTB4np4lkfOdW9NLtOIW5sZjCksF@bGcy$aW-V#;sdsK(h(Z52d3H*v$=}VX%|31L_ zt3vF9?hK?u4WJBWz*eXck3f~1gKBVt8G&l}GOFQ!Q006P&LGs1XGd*mKGYT#Mopwr zgy)v9F$ucA9jw4+R7VG`;3e}Rs=*Hy4>;tmZ4%U$RKVO=9d$^DpgLZG8rWJahzGDX zzV!$cBT)IU`}=(q<|2Lrt6;n%?zA?*X2b_!W4w&o!+b~G2c`?^kRC@J;)|FPZ=!C& zzo;!v`kOnPc~M*Fm9juB)Ka%bE$Kki9!^3X!WEbi_oMdi4o1T$$J|!MM0J=AgRvYI zz;;*|XJKqSgBs{njH3I0-vxXRQK$JaYGm(GBaeNYgN7lfU$@q%fp$l&z*y9EJAiyp zd}mO5d<|pZ6VzV6LJctb3D-}0^xyxS1T@2vW<$(Qya%eIxv0I{g0b*7)IiUo271GM zhU(aN(&Z;ab(j`4z{03ARncsM2|0hhZUi(!4~yVr%z?)-Grq-gnC6r_6Rl8Ry49%L zaun0z15}66es_DF4mGiG)Rxu7Lf9MQ;cE2MzzzZ`cnP)V&rmaqaoVjwa@5T8U@#W3 zcw^MHYlGUVzL*JrM(zDp%!>~(52ifh;#JH+XV`xojx{9cFx^Ep_z(l}BWh*hoOPzb z5aPK}9oEG#?1t)i8D_)ZunWFKUAGqJ+^w35`mP+n4S4q)>;EHxsps9^1Yh7IL%bkn z!P8hC-(qPjcG2CAA*hC?pa!%Rb!Ps+x)|*ee~e%w48}F6vvd-*Mfb2ee)b4dBv9?L z`;bgUo!Y|~6Hj6Synu=E9%`lDS^6i`O2xb4J~XK@Ht`Io70Q9SwiQtW?1Tw%8fpUG zast}hqZo!~Pz7WB;r{VCA66#b*j$3Si9be_Pj%IOz-pn=e?$#&pu`2OFsPDlM)DlO%=KdmTfT}keb-I7SWVjV| z?M|TDyNN;g0+Z9fFXnZ()ag;zC=^wo0!GEA$d}6361B8#Fc)^k=r{*8vqk0_)UDc% zaq%K*i*BRZd5+=u3ghek=f2@iZ*kPpx3c&I)ZyBI`SAj3iDTY$hpG_jkTx`jp|0I> z48=dNI0oEusJWd6K{oDfg_j^&!Nh{!L*qAF6*y^qIX?FOLHh{26IsZia_n@b=0AHgqqnG%P)S< zty}|4P5N+D{rRXfbr`i}H&7kNyYD8F{l4b{4M|XeQK&D~X4EyjgKFS!Oove(xa*Sv z(-6;(I#e}L18t4!crYf%rKq#C8&ly~^9kx2#`OMj4W&Tc?=VzGWmLnB%`RAi_)yfT z-i_LdbEvcN1$FK6KXiw(EUM$m7H@$%gzZoR?TuOqZz2I*n>CiP3$?`OQ8RdGao^uA zJqWeL*)cX&L|w01sDZb$cwbZpEZdO9gxE`urJ5;$|m>!3r2Cx9NVtX(Hp2wK@28-(c|3^R-3O{xQ8e%2l15qmS-sI9DmnrKth*7U`s^zWNMAS*7yYIqDa z;$;804sxN+Mj6!B)U)(Xs6#mvW8gfDj!RJkUWGs4I;?<2p1LpQFf2p-EP5RXBzfjO zK!dO=@dX$M<34vwm<+W-1yKX5hnjI0RL3Jx1N;Hw<9tkrYfuB;gUUaP{*^=j$~|ZO zl@RcPf1`zQusO~~4d5Nd#wagcNAXY%Cc#9Q)#Bl(25X}Bwk;;aE;t;AU>E$1d9d>< z_ZQZjSFC?L5{{7IKlP|RdWf1~l-D$hsZfWhGbX@ssDaHweIJ&fR&qCL02$x7mB^0z zP830X0qbL29AJ*}2x!lK#w0ic)xm1i4E|^F6R3{;88nkeP&T*b1kiuGJgNk4Zo96~juXB|D2nG4)5+ zaDCK(Tc8He5w#+o#iv?)HEM$UFe#qJAo}+`AfOfaWCnh61%u53s0J&dDmFot?~cJZ z95urws1;g+x`szE7hXUueU$%PyNS#Y^xBhAn1Js6d@O`*1F;N_Mm2O4 zHIPfF!}}OD^B1Ty6zhwtmjbmiA($LE3$YQd#o`z}Ai%%XWico5jsaeP|GrKqAw3E6 zQ4Q`zE#)5=imy>4PZK4;KckYU0aiw>Ks}2$L9I{+)PVY;R^}(v#FnF0XcuaL$2W3HcLQ#KYQG2S zObkTY^?V}DNF1NR-^9sVbmc!j~e(*)S-HT zIwPM^*DggIx7T@511W==aC7wk_kZ6JP{HA-j%K4qz81B_zoNF{5URt|s1E-`?d3nH z`tMMuKS5lVo(@$$E2@4$)BsDN&P=tq0iM5NTPrXa)$tfBI0rS;Ur-%wv-p1008XJA zzG*(P{5PnMqsDXf5}=koC930$sD6sZA!f!dm<}gf`bJbghfqIif1(cU6OVxZ_Z;=X_=uWu(m?ke$cP$9C~9fL zQCm_4)nRo@Z;d*nJy3^t3~G<(TK*dIf95f4$Iqa5g@CS8iA1i!?@=S1h8p2=)QYS_ z|Di*5d>%FMzfc2vimLaY#RC(&{Isa_5Y(XzL#<>@WJ^8Y5CU5IF{qhNaT&hls0tfU zGdhOq_y*>}m#6^-CvgMJiW*R9R6CVWXQl~i>D!^UaxkjB8JJl2e+>Z*U?1vw97i3l z2dJ67N6kEDQrA!rYG650pW2G3EvbgVSPRurPt>RUN7SjGj2g%S)YfcMy6*pB0y@R# zlz`V!9X~?N_+QjviXY?}&WRduCDf^|iyBBXOK*d!-wieJq2>hCR?kMQ&^7de2|Od9 zjuIww86l_<7DhEx3AJPmP&4Xc={->OJXC{IQCqMA)$uw@-;J92@0NZaby!~|&Q;0?O<*MI%*;fs#41bQgKF;#Y6WhgR`eaJ zd<-w83#34GkR8=_b|Ggts)r*c2XB`_QD;TVEz zFe7?r2xvsFP}e0&YB!L0sD{&`_A(c0sf(eupcHC_8llRyM9r|f#mAry0zj)tcY5%MrIfEpAn0XN7b8$ zYIh_0|NZ|ie}I2Mh-&aU>QAqys0QPvbu&zdiswe%|1zkpYHI1dQT4`Hd?~8E?Wh$x zYVpe!e~2k`|KD3eqI7PlGN3xhgZdymqNpvZjajiH`v3c%$pkdQwWy`vgW8G+)a^KjTH>3Q{sL9r7wiU<(9D3kw)s){ z;ixn44Q9q#s4eM-I%~s&x&JCKfdq9h8FhM>TKpO|BK{OL!%7+4k4JlR3g#t!KL+D- z48=ql-Tf|#If!>e9olI)7}ue;GFv9kEqU=w?pl3=TB4Sy!_p5`@dwLaidx#87XKa9 z&|UMb89T(4OM}|7{HPTzhjpNc$K2xKC#8MS1WPi8_`%XtTN4gW&@IK4q_t(P#1%SekVn8V_EQF~PqRj>+bZyTV# z11(T9Z-eTvFKXq+V=yj4ZRr8jbvuu$e+@O!d&opR-)jOo?eRk046>jKgrP=U!Qyqz zwy2r)Ms+aC;xjD%3#!9isDU4}{L`p@ZecP3j zMukMU^S}!y{G}7L>=<0Il2Fu*-H{M z!Y`%%!O14IQ`MRKHJQ;OMR$(aq z>Jex{;34V@S1ymc_pQyL7)<(XEQ$ZK^nX#`{-C_B;likRP1FagCu-|{Kn-jPY9(f) zz8}j`1NZ(%K!@chYLEX!E$L&_3jB+z7%QJ!+N7wJ2t}38k7}qas(ejUdo3*93sr77 zYUwAV+FOFu^L*gkqJAS{<#!zgq6Ux}^I;a$7p)QMTJ^>WxE}S} z5njNRpNiU&1*ie7#1#7beT{7>WX7<$lXvQk&(t}U~&4{X(54E%4D#azT&qpss5RQ_7j zZ^=p2S$b{;7INisqRvPavkQ7zNSH_Dp#DLmKdSr;RD=65 z2i`{2i(kYY;)19N)ItrcAFAFQ%#IO7xc|Wfo|2#j5)^d}7DHW^=BWI>mOca3;7-(x zZ=eSB88zdy;jW`%sCY}%0Ec1$TxjX%Q7iW%ocpgog9D4Xg849*cwN*;`=CZX-_j3Q z{0{2S#VGFnAjyE5Q4Q392BHQq3pL>Fr~zNI{7)87?Uk?*qkqKaP}B(LT70K@3AIJ9 zQ8PrA-K!oMrK{XVm zv^xtSsB%?MGwy8Z<5BIcxBTBxEBMUPlaz7g3n2Y@zB&Xn^MR-t&$Ref)SjI~o%R@I z-3$t%mbw`#eJtv5ZbMDrDr%qsgufJS%|b7R! ze`V0WG8jz$5>y8fm>=(>2A-mVJN03xdtMv$2gkRl6&j8@Q;SgT9mDkW?|V)_ACiO> z?eBHe2cjsdqZ(!pRJkdr87)Q)_$cac#kUv(6IXJ#DJAA4UI7bZFVy#CH3s80^z7;9nq zssaB0ymxw4FTnr5--}btjl2n#roa$vk9$!|ovC_&uMAc}{pd_U{n@=2OXF+Q%7oPj z@c(Ce-=Xr4V|@&$>Gr-MHYWZ(mc*+b0qt4JS^@t5-ET0e;&-SmS%%f|Bo@O|wcQLF zpni0ILH(+2L7k1gmVOfT<8uY$<9+iL>bEAKj?4FA5Qt7f67&zm3`Xr$C~7IgQCn5h z(p#fC?1MT(BQ1R@>dUwSb=VG|&eTcN7T-gi{*TBOdcKTx-3W`II;x2JEof@-v8d}g z57p4GsMCJM;;&KHEM7gAp9O=7mqZP)CF)FcL#>pDT7mKC|9}7Y69J8M4rKy&0pvJA_G5E0`74Q65x#MNuEDil_ngG{48hy8n|1=oBw8x1$<5j@sk1 zsMCHOb@*PP{I`*3O>7D33%kzpPoUbnhn{Bofq?clK|?o? z45+;iLoHop^j|xR_d@OENYudRpw7U0R6F}nTXF_f|B=N%q6QMw$hB9X5%*sssYZeZ z(gxLFe^kW@sD|gE8eVJp`z-$)YNhU?4)G(@jGv>n>?3LgV>fpHpb~^iuY+p0Rb%eI z5_*uJy&8sUZ~|(trl9t2G3wBq#4tRI`u4|c;yMmTtypQyjdigCjV-(`E z%(cc`kE?XV2#o_PQ@fv8>FO5{d;unKqtv=l{Ads5K~G(a7~ zrl?!d0ac-grT0TE<#5y?oP-+a3e?^oLapc-)NOczVfYF&W45ktrM;R2^p{9))QC5u zmi{&7!ld81r7eq!_d$IxmY~kg7F37FP-o_%rQbkJ>@})Lz`m%J*@F6l?nkwI z4RyvoVOsk4rS9qWq$q|EZ;9HwQK*88Q1^X5Y76e74qc*NZp8|qX4)Nf27W+wxDs`p z4`WVzh+2W5-mYAB^i-iT0Tt|ky3gZL1KErkz-3f}Z&5Qy(#QRkTL85JKclYc0?dX- zP>1X}s=Z`=T|1>v6KR3^PK@Zw{Z~h;NKiw+qfYZR)ZV{B4Xju{*Fg)^UXMY|WG3pv zwAS*Eptj~IYTz;YyYEA0)XFtReUQeYK1kd9bN_XUcaxwG$63^=eT3@Z9cmBb4RGaB zn7L5{E{{6Abx<8Qwe;SoGcz1@7=J{yv(VDlp!(VFSw;lrAmKD>1wNua7>NhEr7D3s zWbIJjfj+1X2U&ayYCyA46Iy{fLwisiT|rIgzWKrQ5)5+JChjV+R{6s z8XAPUc4JXzVlHZCJ2566LT%AW)NQ$L@xM?j@*cHfQ3v}c#J~R~pn_>o4P`+U%#WH; z2~>rusB-mCGi!l5^@C6|o^J6qsDU3rt>`J#8Tl7Aup~p=uVe`N|NEb21fr7B1$BSB zqdM$`8o*%G%8a-4xu~g?*A|XTH1-0 zF~?kkTH-yZ8U112LJjyY?2V7H2(}#New1dReiiRydrZk8*KP2yF)l!@I!Ej@~w=y|M$b%(ohi-vRm z)xjzfG{a4(j&`EH<-egCx{O+(hp6&zEdM|3N<7|(0AF7mh}rNNX2p~v-2lp>4s8vy z4XWLKBUu9d=!~_D2-M-bjGDK?| z(hs4w@HA>b*N}ER-#r4l90yTc~KvvBB;Yz6Sa43Fc0=dZPilL3av%m zj!l-n4KowphdLwoQ2jI+r(46Z>`tH!2`jNI#vSh(u7MiBFjNO)Py?8R+JYshmDp(U zUr{UhJ8C7aqn7-k`5LtXz8_ru_~^g?sR^iHc2t2v7B7cd%9^O#(Ghjnx?BEO%t3rA zs@{Io7M(<`&<$*Y&rsiiZzj0^7Gxvp`|uh)jWp|z_J;&2-W|0>gHTI43AF{&P%~eH zIupB4D-?k$e**Qvx@GDAp#~g%q8ngZGdpU+g(q_VGZH9Af@abI^WqdM5P|CWH2QA` zYHvSTzVD|1{hx94#lzA#3U!taVH1m3)m_p)aW067y%*UTV~Yf;|Fipb)A+ zRn*8@qGr+))zM_sK$oEg7=b!`$4~?M!{QH7XXQPr-WSx0C7$dKaWd3^(p%gMC7=%T zq8coVTJk!mL(~a1qd^uQhvCF$V;EjQO(4z`YuF4$t!N(904t*g)DTNzXJkb^-zoz7 zYjz9jclsjg8a_jfJpWX;WQ9--6+>;!H<$$*q8c8CTCvHfv$P5Q*ATUJ4^dn6(&C@d z|KI<_n&xJh3e|8{R7YVJFOMO_YomTt`dNITh)# zH{YSC_6DN=zyDc4KwGc_RpA(F>2ISxJTFlVel%mxaOIMtI?jWtU(w=?Q02R$wsfe) zC!!`c*IbRBPWLVXn)yD|Qk_7J_#$cvAEG*Vg=#qZOlK0*l4d~F&t-#_viUb{|`IsFKVNQI8x-MyEyM{wBn0R5-AD@j-4fRG{-w~)K zpMkoDD^M%E4mI=5sEI^a`e~1VW^e&D!aJx_{|r^(6>6r@=C~CJL^TkMO3!KWLS|XB z1_qF?Co}I$HOg}zb=xXwR6O31D17ZG+1N^lafIVo;aTK8qToPGhDlM+aV$eQ7SI1A z*0JZwL;N4gJ)r&>;&XT#k+<9Gsf?aS#0TIw|37~dh(aaKmhU{_jMnHu8Y#m2D`|y! z^?bB}Wx=a7vWj|<&k*aR3ib0^8yiTgXM;0jtj68Ws~3@@>8Ln7goO);dg{zQ0F7Bo_5w=9m?xKr~0a|$<+7w z+rU@K8v4s$g>N(Q!c?eDWxkUBXBq!9h;Uc(-eD0dD>hJe9qDG z^3f=_h}Ry^w}XN?DWvPNhta*Y%y*=<;EjByShzoBw%IK5keQJ5Q7S~IlSuDIup!}x zq(9|-&s&5xKals7x3bmkNx586+5Zs)R#GS*8H4pwxI1Z)&-bLIB&`HaAh9luSH$Ji z`GvPQZ{)L&$#f^bA>~_<_?CEY!g@M6e3wbfZE4Nu-?xbdp76#cW1SUxg~uqAfKK%U zlAoT2KUut>HNYP@z6Y*|Z!O{7mL7v}Ey~}*ExdUtGl#r+Scdpq+PjF}k2HAQ8rV+a zXWqMHJm>v}^!en6lQzrBlpx%VcbN_3AJTgfUPxLS>f9&(H*XWtQd^lPbo?jzdfpMP zNjW`(=-+pZ$T<=-Qh0z>Xh-20g!M(#liDhzrd)RmuOk1Yh1)VyJ!i?Uj{|THZ9KP5 zZ;;lC@@=f#B=X1cW{j@&=UGoAf&#l}Fh7+_k=CBH)z(1`DyAboguGXz6($_{yrN!i zBBd?i4)&x>Eh`hycQQS5G`T8q8aRLf=~249XND z-hlKfl+o`%EaI7YyQmV6{zlYOjIyICH;ud|)b~)ogv&_R4_sFU^N-SZlA))Ljj|Dy z>Jk5zf;Y%p>CdGyg{u-zj0t%4ET_!Z&ov@fc(?Ip;-x8HZ^~BU{hhi|c#BeJFX?)+ z>0b+6C*h(>@-(1e3*wcDx3b1}k)Db4CRm&|7GXUB4ERr+N~2#tQApoS{b{_z$@q@^ zR-_%mwbsuUYvW)P_J1FVYb>F!wN#$Y(^08B?{+HwW)&L{Pr;jj_$AW+z;yT>P^3l)3$NIi0_TWLBqv`V@?OVq2kqN%)Pt{k)M+3L6Z6dHYgRCqH?W z$h<>(O5Ui%i()78##-4BtiW4`a@k2wOP_}*=Rg0kNZ4nsccsxHUyZOB;pybnq>P@= z#5eI4rUCvq@;&4Io>zaYq~R??`ftSbB%;m^8+Z)De~`{U68fG{<~`|CqS60rD}0mD z)#5Enyf}qVTKa4Xp0jWX8$>1SOZpqvk8eKiQ#rgxvCH)O? z|NJ9JSZt*Zn@uVB*k6Eugd(j4Z&Kp=bGtcjG{W#d(thAw;iA4( zl&emetf=Q3%2g!4HOBM^G$64Vk-NP62_L2KW_-yTgRq{Bl;dBJ_@7LaJ4;;(3<98M(un+RIw_z@Md<1svr#cW`+iBBLrd+Li$NxX&R zjN)BF%5G~ZfD+e;f6sfshOvUQ)s)lo7e-(X^7ZIva2VyHQbtc1;&lkmw7Nk!#=@sb zuSGaFPSh7fPaA8dW;5|*HU#0}xCYw;^K;A(74G#gAi z%uKrls8<>b@|GjNsg?E5e?EzQNH}GcekHD_1a{yZ>7u@|8a?G=T7DcF%@f&>m3cy5 zN!|)pM#(RDm-Ala%|jbiQBP~aUOoyYWkh-kU|il1tNf6(hSosu<@(Lw^`w#k*%4F7)%B0v^{BQi2q8x z|5<)B>g^{jHE#jRbtFB4@Ic<)yv4~si(#ZcBfpgXf-Gv4MRFQzOhzpmz_KI*CI@C~zgIPHJKyN>s^u1;49JhwuZD72bzI{X=b zw@P;?cbJau@OGo|lDv8@5nqTcF}sy5LD>St^+czWsiY^Q{0YL5&#zY2D@oxaq}Cvz zIN{M>6?#DU5_xH?v6hrM%DW}9mH*Fc)Yp@j&WiBvbWvX`>Ws5Cy3yu%;?-PPcmLB; z_!)&$l9`5#7rgy>tCOCD!g~6AHL!xDza*ZI^g_Jp38z;fo?Vo$Yh`CzU8SEQT!TUU z?K<`?q|AN&1$mypEegcN-^u*Z3Y;Upgm4PHK*iQHaESq2jM>>z(Gc{g~E zlbF>y{~P<07KHJ6M_Aodq+QTo5Rp%L8b3kgE(X)^Nz15BnJ@~667Nl3I>Jq@;|esE zi?B&ol&7>tF{@N-jJs;_@tjtWpH+g>|zm_uXc|g4^47@DyWcU{U zM_O{i_b@(hHtMt`eY?*8QW7GcsAQBO(gnNIcq!aKJPnmAQm#FnceMeiPEpb$pPi(S zp^l#1q&J}M|43WK+kv+$@h#*hqMg>Rn9qAm;uI48qkx{R_=0yaX{UJg{Etd6c^~rj zc1gapgg;R32oB*5;EjAHQm;PoBsRDq#79#0D(_$l9Y;NbqS){Mb_z73aBYl2W=ASN z|Ej^dqu#b%KwN@feaMv!8^?oXVTyX z3QyxLOMVLm_#^q92^X@?R5T~)St#?`HSGJ0=Xr}z?keSm;#}T0gomS#H)iBIEwYAg zlm3~E;dG$q1`V9Byd_wZ^!nI@&YELF@@G>nu9dH1jwSsJZ(`c2#`~wW5tDk6&s+lK zwg1g6@fMZGTW&{7t4bpoXrQn)FcLRYZawbg-A2Bi5BM#nB ziFjkmOtv!KCL)h4vWr542>)#HfA9)vdfxMnB0k3klIyFPjI}hC8$+4xbo3hI5IW-I*4+=I`k@P)h;81_|TlW8mm??)Txx3ra= z@E6MU#Z}}rCT%5kDic1$8->0u5zo*62Fw41Qo!oF1pA)}tfQ=!S%CCVOM6WCJe_19 z{tc!ko|$lS%5LGEL?;!joj1e}TD_a3kFxe6&!4~85)%7RD46#bQvN00o`LP9LUOAx zfR6TAxD?@O&e-9`Ru)N_RN2gEB;roT(_T_-|65MWu}t2mAnI%pOtt$!cFK%Pg>r+ zlzV3RZ3yd$O&fZmQf?h>9n(Mm=})kaR#2I3^gno7QJ^hv^RVLU6p)CRT@ghQ8xex@(=~V`Rgr z(1Nu3q^a%|{zq-z|52%)m1}Apg%K}Aos3wGvPG@oG*Pz9=yPr8)Zs6KrmlP$wB_8( z#;JGI4h;AqAV&V+ym`Y5&b*x\n" "Language-Team: nuxsmin@syspass.org\n" "Language: en_GB\n" @@ -25,12 +25,12 @@ msgstr "" "X-Poedit-SearchPath-1: ../../../../lib\n" "X-Poedit-SearchPath-2: ../../../config\n" -#: ../../../../lib/SP/Bootstrap.php:267 +#: ../../../../lib/SP/Bootstrap.php:278 #, php-format msgid "Versión de PHP requerida >= %s <= %s" msgstr "Required PHP version >= %s <= %s" -#: ../../../../lib/SP/Bootstrap.php:269 +#: ../../../../lib/SP/Bootstrap.php:280 msgid "" "Actualice la versión de PHP para que la aplicación funcione correctamente" msgstr "Please update the PHP version to run sysPass" @@ -53,7 +53,7 @@ msgid "Actual: %s - Necesario: 750" msgstr "Current: %s - Needed: 750" #: ../../../../lib/SP/Core/Acl/AccountPermissionException.php:45 -#: ../../../../lib/SP/Util/ErrorUtil.php:132 +#: ../../../../lib/SP/Util/ErrorUtil.php:142 #: ../../../modules/web/Controllers/Helpers/Account/AccountPasswordHelper.php:96 msgid "No tiene permisos para acceder a esta cuenta" msgstr "You don't have permission to access to this account" @@ -61,12 +61,12 @@ msgstr "You don't have permission to access to this account" #: ../../../../lib/SP/Core/Acl/AccountPermissionException.php:45 #: ../../../../lib/SP/Core/Acl/UnauthorizedActionException.php:46 #: ../../../../lib/SP/Core/Acl/UnauthorizedPageException.php:45 -#: ../../../../lib/SP/Util/ErrorUtil.php:129 -#: ../../../../lib/SP/Util/ErrorUtil.php:133 -#: ../../../../lib/SP/Util/ErrorUtil.php:137 -#: ../../../../lib/SP/Util/ErrorUtil.php:141 -#: ../../../../lib/SP/Util/ErrorUtil.php:149 -#: ../../../../lib/SP/Util/ErrorUtil.php:156 +#: ../../../../lib/SP/Util/ErrorUtil.php:139 +#: ../../../../lib/SP/Util/ErrorUtil.php:143 +#: ../../../../lib/SP/Util/ErrorUtil.php:147 +#: ../../../../lib/SP/Util/ErrorUtil.php:151 +#: ../../../../lib/SP/Util/ErrorUtil.php:159 +#: ../../../../lib/SP/Util/ErrorUtil.php:166 #: ../../../modules/web/Controllers/ErrorController.php:124 #: ../../../modules/web/Controllers/UserPassResetController.php:94 #: ../../../modules/web/themes/material-blue/views/upgrade/index.inc:13 @@ -75,7 +75,7 @@ msgstr "Please contact to the administrator" # Not available #: ../../../../lib/SP/Core/Acl/Acl.php:294 -#: ../../../../lib/SP/Services/Auth/LoginService.php:600 +#: ../../../../lib/SP/Services/Auth/LoginService.php:604 msgid "N/D" msgstr "N/A" @@ -96,24 +96,24 @@ msgstr "Action" #: ../../../../lib/SP/Providers/Auth/Ldap/LdapMsAds.php:155 #: ../../../../lib/SP/Providers/Auth/Ldap/LdapStd.php:110 #: ../../../../lib/SP/Providers/Auth/Ldap/LdapStd.php:142 -#: ../../../../lib/SP/Services/Auth/LoginService.php:217 -#: ../../../../lib/SP/Services/Auth/LoginService.php:235 -#: ../../../../lib/SP/Services/Auth/LoginService.php:386 -#: ../../../../lib/SP/Services/Auth/LoginService.php:453 -#: ../../../../lib/SP/Services/Auth/LoginService.php:561 -#: ../../../../lib/SP/Services/Auth/LoginService.php:604 +#: ../../../../lib/SP/Services/Auth/LoginService.php:220 +#: ../../../../lib/SP/Services/Auth/LoginService.php:238 +#: ../../../../lib/SP/Services/Auth/LoginService.php:390 +#: ../../../../lib/SP/Services/Auth/LoginService.php:457 +#: ../../../../lib/SP/Services/Auth/LoginService.php:565 +#: ../../../../lib/SP/Services/Auth/LoginService.php:608 #: ../../../../lib/SP/Services/Ldap/LdapImportService.php:238 #: ../../../modules/web/Controllers/Helpers/Account/AccountSearchHelper.php:253 #: ../../../modules/web/Controllers/Helpers/Grid/AuthTokenGrid.php:106 #: ../../../modules/web/Controllers/Helpers/Grid/ItemPresetGrid.php:107 #: ../../../modules/web/Controllers/Helpers/Grid/PublicLinkGrid.php:111 #: ../../../modules/web/Controllers/Helpers/Grid/TrackGrid.php:105 -#: ../../../modules/web/Controllers/LoginController.php:102 +#: ../../../modules/web/Controllers/LoginController.php:120 #: ../../../modules/web/Controllers/UserController.php:278 #: ../../../modules/web/Controllers/UserController.php:312 #: ../../../modules/web/Controllers/UserController.php:373 #: ../../../modules/web/Controllers/UserController.php:412 -#: ../../../modules/web/Controllers/UserPassResetController.php:187 +#: ../../../modules/web/Controllers/UserPassResetController.php:190 #: ../../../modules/web/themes/material-blue/views/account/account-editpass.inc:55 #: ../../../modules/web/themes/material-blue/views/account/account-editpass.inc:61 #: ../../../modules/web/themes/material-blue/views/account/account-history.inc:91 @@ -151,7 +151,7 @@ msgid "Acción no encontrada" msgstr "Action not found" #: ../../../../lib/SP/Core/Acl/UnauthorizedActionException.php:46 -#: ../../../../lib/SP/Util/ErrorUtil.php:140 +#: ../../../../lib/SP/Util/ErrorUtil.php:150 #: ../../../modules/web/Controllers/AccountFileController.php:261 #: ../../../modules/web/Controllers/AccountHistoryManagerController.php:59 #: ../../../modules/web/Controllers/AccountManagerController.php:77 @@ -200,8 +200,8 @@ msgstr "Action not found" #: ../../../modules/web/Controllers/NotificationController.php:288 #: ../../../modules/web/Controllers/NotificationController.php:315 #: ../../../modules/web/Controllers/NotificationController.php:348 -#: ../../../modules/web/Controllers/PluginController.php:98 -#: ../../../modules/web/Controllers/PluginController.php:117 +#: ../../../modules/web/Controllers/PluginController.php:103 +#: ../../../modules/web/Controllers/PluginController.php:122 #: ../../../modules/web/Controllers/PublicLinkController.php:71 #: ../../../modules/web/Controllers/PublicLinkController.php:105 #: ../../../modules/web/Controllers/PublicLinkController.php:167 @@ -244,7 +244,7 @@ msgid "No tiene permisos para realizar esta operación" msgstr "You don't have permission to do this operation" #: ../../../../lib/SP/Core/Acl/UnauthorizedPageException.php:45 -#: ../../../../lib/SP/Util/ErrorUtil.php:136 +#: ../../../../lib/SP/Util/ErrorUtil.php:146 msgid "No tiene permisos para acceder a esta página" msgstr "You don't have permission to access this page" @@ -280,14 +280,14 @@ msgstr "Session cannot be initialized" #: ../../../../lib/SP/Services/Account/AccountService.php:227 #: ../../../../lib/SP/Services/Account/AccountService.php:232 #: ../../../../lib/SP/Services/Api/ApiService.php:129 -#: ../../../../lib/SP/Services/Api/ApiService.php:227 -#: ../../../../lib/SP/Services/Api/ApiService.php:235 -#: ../../../../lib/SP/Services/Auth/LoginService.php:187 -#: ../../../../lib/SP/Services/Auth/LoginService.php:351 -#: ../../../../lib/SP/Services/Auth/LoginService.php:500 -#: ../../../../lib/SP/Services/Auth/LoginService.php:505 -#: ../../../../lib/SP/Services/Auth/LoginService.php:537 -#: ../../../../lib/SP/Services/Auth/LoginService.php:644 +#: ../../../../lib/SP/Services/Api/ApiService.php:229 +#: ../../../../lib/SP/Services/Api/ApiService.php:237 +#: ../../../../lib/SP/Services/Auth/LoginService.php:190 +#: ../../../../lib/SP/Services/Auth/LoginService.php:354 +#: ../../../../lib/SP/Services/Auth/LoginService.php:504 +#: ../../../../lib/SP/Services/Auth/LoginService.php:509 +#: ../../../../lib/SP/Services/Auth/LoginService.php:541 +#: ../../../../lib/SP/Services/Auth/LoginService.php:648 #: ../../../../lib/SP/Services/AuthToken/AuthTokenService.php:311 #: ../../../../lib/SP/Services/CustomField/CustomFieldService.php:203 #: ../../../../lib/SP/Services/Export/XmlVerifyService.php:108 @@ -306,7 +306,7 @@ msgstr "Crypto module cannot be loaded" msgid "Error al generar datos cifrados" msgstr "Error while creating the encrypted data" -#: ../../../../lib/SP/Core/Events/Event.php:56 +#: ../../../../lib/SP/Core/Events/Event.php:57 msgid "Es necesario un objeto" msgstr "An object is needed" @@ -320,17 +320,17 @@ msgstr "Invalid icons class" #: ../../../../lib/SP/DataModel/PublicLinkListData.php:88 #: ../../../../lib/SP/Providers/Auth/Ldap/LdapConnection.php:190 -#: ../../../modules/web/Controllers/AccountController.php:227 +#: ../../../modules/web/Controllers/AccountController.php:226 msgid "ON" msgstr "ON" #: ../../../../lib/SP/DataModel/PublicLinkListData.php:88 -#: ../../../modules/web/Controllers/AccountController.php:227 +#: ../../../modules/web/Controllers/AccountController.php:226 msgid "OFF" msgstr "OFF" #: ../../../../lib/SP/Html/DataGrid/DataGridBase.php:303 -#: ../../../../lib/SP/Mvc/View/Template.php:122 +#: ../../../../lib/SP/Mvc/View/Template.php:126 #, php-format msgid "No es posible obtener la plantilla \"%s\" : %s" msgstr "Unable to retrieve the \"%s\" template: %s" @@ -352,11 +352,11 @@ msgstr "Encoding error" msgid "Respuesta XML-RPC inválida" msgstr "Invalid XML-RPC response" -#: ../../../../lib/SP/Mvc/Controller/ControllerTrait.php:64 +#: ../../../../lib/SP/Mvc/Controller/ControllerTrait.php:71 msgid "La sesión no se ha iniciado o ha caducado" msgstr "Session not started or timed out" -#: ../../../../lib/SP/Mvc/Controller/ControllerTrait.php:114 +#: ../../../../lib/SP/Mvc/Controller/ControllerTrait.php:124 msgid "Acción Inválida" msgstr "Invalid Action" @@ -398,41 +398,69 @@ msgstr "Invalid filter type" msgid "Tipo de objeto incorrecto" msgstr "Wrong object type" -#: ../../../../lib/SP/Mvc/View/Template.php:274 -#: ../../../../lib/SP/Mvc/View/Template.php:276 +#: ../../../../lib/SP/Mvc/View/Template.php:278 +#: ../../../../lib/SP/Mvc/View/Template.php:280 #, php-format msgid "No es posible obtener la variable \"%s\"" msgstr "Unable to retrieve the \"%s\" variable" -#: ../../../../lib/SP/Mvc/View/Template.php:322 -#: ../../../../lib/SP/Mvc/View/Template.php:324 +#: ../../../../lib/SP/Mvc/View/Template.php:326 +#: ../../../../lib/SP/Mvc/View/Template.php:328 #, php-format msgid "No es posible destruir la variable \"%s\"" msgstr "Unable to unset the \"%s\" variable" -#: ../../../../lib/SP/Mvc/View/Template.php:341 +#: ../../../../lib/SP/Mvc/View/Template.php:345 msgid "La plantilla no contiene archivos" msgstr "Template does not contain files" -#: ../../../../lib/SP/Plugin/PluginManager.php:113 -#: ../../../../lib/SP/Plugin/PluginManager.php:256 +#: ../../../../lib/SP/Plugin/PluginManager.php:170 +#, php-format +msgid "Versión de plugin no compatible (%s)" +msgstr "Plugin version not compatible (%s)" + +#: ../../../../lib/SP/Plugin/PluginManager.php:192 #, php-format msgid "No es posible cargar el plugin \"%s\"" msgstr "Unable to load the \"%s\" plugin" +#: ../../../../lib/SP/Plugin/PluginManager.php:194 +#: ../../../modules/web/Controllers/Helpers/Grid/PluginGrid.php:101 +msgid "Plugin" +msgstr "Plugin" + +#: ../../../../lib/SP/Plugin/PluginManager.php:219 +#: ../../../../lib/SP/Plugin/PluginManager.php:339 +#: ../../../modules/web/Controllers/PluginController.php:213 +#: ../../../modules/web/Controllers/PluginController.php:216 +msgid "Plugin deshabilitado" +msgstr "Plugin disabled" + +#: ../../../../lib/SP/Plugin/PluginManager.php:254 +msgid "Plugin disponible" +msgstr "Plugin available" + +#: ../../../../lib/SP/Plugin/PluginManager.php:264 +msgid "Plugin no disponible" +msgstr "Plugin unavailable" + +#: ../../../../lib/SP/Plugin/PluginManager.php:294 +msgid "Plugin cargado" +msgstr "Plugin loaded" + #. (itstool) path: action/text -#: ../../../../lib/SP/Plugin/PluginManager.php:245 +#: ../../../../lib/SP/Plugin/PluginManager.php:319 #: ../../../config/actions.xml:535 msgid "Nuevo Plugin" msgstr "New Plugin" -#: ../../../../lib/SP/Plugin/PluginManager.php:246 +#: ../../../../lib/SP/Plugin/PluginManager.php:320 #: ../../../modules/api/Controllers/AccountController.php:71 #: ../../../modules/api/Controllers/AccountController.php:103 #: ../../../modules/api/Controllers/AccountController.php:139 -#: ../../../modules/api/Controllers/AccountController.php:185 -#: ../../../modules/api/Controllers/AccountController.php:235 -#: ../../../modules/api/Controllers/AccountController.php:310 +#: ../../../modules/api/Controllers/AccountController.php:189 +#: ../../../modules/api/Controllers/AccountController.php:240 +#: ../../../modules/api/Controllers/AccountController.php:315 #: ../../../modules/api/Controllers/CategoryController.php:63 #: ../../../modules/api/Controllers/CategoryController.php:92 #: ../../../modules/api/Controllers/CategoryController.php:122 @@ -490,7 +518,7 @@ msgid "Método ya inicializado" msgstr "Method already initialized" #: ../../../../lib/SP/Providers/Auth/Ldap/LdapActions.php:119 -#: ../../../../lib/SP/Providers/Auth/Ldap/LdapActions.php:125 +#: ../../../../lib/SP/Providers/Auth/Ldap/LdapActions.php:126 msgid "Error al buscar RDN de grupo" msgstr "Error while searching the group RDN" @@ -518,13 +546,13 @@ msgstr "Error while searching the group RDN" msgid "Grupo" msgstr "Group" -#: ../../../../lib/SP/Providers/Auth/Ldap/LdapActions.php:200 -#: ../../../../lib/SP/Providers/Auth/Ldap/LdapActions.php:204 +#: ../../../../lib/SP/Providers/Auth/Ldap/LdapActions.php:205 +#: ../../../../lib/SP/Providers/Auth/Ldap/LdapActions.php:210 msgid "Error al localizar el usuario en LDAP" msgstr "Error while searching the user on LDAP" -#: ../../../../lib/SP/Providers/Auth/Ldap/LdapActions.php:249 -#: ../../../../lib/SP/Providers/Auth/Ldap/LdapActions.php:254 +#: ../../../../lib/SP/Providers/Auth/Ldap/LdapActions.php:259 +#: ../../../../lib/SP/Providers/Auth/Ldap/LdapActions.php:265 msgid "Error al buscar objetos en DN base" msgstr "Error while searching objects in base DN" @@ -594,7 +622,7 @@ msgid "No es posible inicializar" msgstr "Unable to initialize" #: ../../../../lib/SP/Providers/Notification/NotificationHandler.php:124 -#: ../../../modules/web/Controllers/AccountController.php:926 +#: ../../../modules/web/Controllers/AccountController.php:925 msgid "Solicitud" msgstr "Request" @@ -1121,7 +1149,7 @@ msgstr "The account doesn't exist" #: ../../../../lib/SP/Services/Api/ApiRequest.php:79 #: ../../../../lib/SP/Services/Api/ApiRequest.php:113 -#: ../../../../lib/SP/Services/Api/ApiService.php:229 +#: ../../../../lib/SP/Services/Api/ApiService.php:231 msgid "Datos inválidos" msgstr "Invalid data" @@ -1130,7 +1158,7 @@ msgid "Fomato incorrecto" msgstr "Invalid format" #: ../../../../lib/SP/Services/Api/ApiService.php:96 -#: ../../../../lib/SP/Services/Auth/LoginService.php:137 +#: ../../../../lib/SP/Services/Auth/LoginService.php:138 #: ../../../../lib/SP/Services/UserPassRecover/UserPassRecoverService.php:103 #: ../../../modules/web/Controllers/UserPassResetController.php:124 msgid "Intentos excedidos" @@ -1145,54 +1173,54 @@ msgstr "Wrong parameters" msgid "Acceso no permitido" msgstr "Unauthorized access" -#: ../../../../lib/SP/Services/Auth/LoginService.php:157 -#: ../../../../lib/SP/Services/Auth/LoginService.php:456 -#: ../../../../lib/SP/Services/Auth/LoginService.php:463 -#: ../../../../lib/SP/Services/Auth/LoginService.php:571 -#: ../../../../lib/SP/Services/Auth/LoginService.php:576 -#: ../../../../lib/SP/Services/Auth/LoginService.php:615 -#: ../../../../lib/SP/Services/Auth/LoginService.php:620 +#: ../../../../lib/SP/Services/Auth/LoginService.php:160 +#: ../../../../lib/SP/Services/Auth/LoginService.php:460 +#: ../../../../lib/SP/Services/Auth/LoginService.php:467 +#: ../../../../lib/SP/Services/Auth/LoginService.php:575 +#: ../../../../lib/SP/Services/Auth/LoginService.php:580 +#: ../../../../lib/SP/Services/Auth/LoginService.php:619 +#: ../../../../lib/SP/Services/Auth/LoginService.php:624 msgid "Login incorrecto" msgstr "Wrong login" -#: ../../../../lib/SP/Services/Auth/LoginService.php:216 -#: ../../../../lib/SP/Services/Auth/LoginService.php:223 +#: ../../../../lib/SP/Services/Auth/LoginService.php:219 +#: ../../../../lib/SP/Services/Auth/LoginService.php:226 msgid "Usuario deshabilitado" msgstr "User disabled" -#: ../../../../lib/SP/Services/Auth/LoginService.php:270 +#: ../../../../lib/SP/Services/Auth/LoginService.php:273 msgid "Usando clave temporal" msgstr "Using temporary password" -#: ../../../../lib/SP/Services/Auth/LoginService.php:282 -#: ../../../../lib/SP/Services/Auth/LoginService.php:288 -#: ../../../../lib/SP/Services/Auth/LoginService.php:306 -#: ../../../../lib/SP/Services/Auth/LoginService.php:312 +#: ../../../../lib/SP/Services/Auth/LoginService.php:285 +#: ../../../../lib/SP/Services/Auth/LoginService.php:291 +#: ../../../../lib/SP/Services/Auth/LoginService.php:309 +#: ../../../../lib/SP/Services/Auth/LoginService.php:315 msgid "Clave maestra incorrecta" msgstr "Wrong master password" -#: ../../../../lib/SP/Services/Auth/LoginService.php:297 -#: ../../../../lib/SP/Services/Auth/LoginService.php:321 +#: ../../../../lib/SP/Services/Auth/LoginService.php:300 +#: ../../../../lib/SP/Services/Auth/LoginService.php:324 #: ../../../../lib/SP/Services/User/UpdatedMasterPassException.php:45 -#: ../../../../lib/SP/Util/ErrorUtil.php:144 +#: ../../../../lib/SP/Util/ErrorUtil.php:154 #: ../../../modules/web/Controllers/ConfigEncryptionController.php:68 #: ../../../modules/web/Controllers/ConfigEncryptionController.php:142 #: ../../../modules/web/Controllers/Helpers/Account/AccountPasswordHelper.php:116 msgid "Clave maestra actualizada" msgstr "Master password updated" -#: ../../../../lib/SP/Services/Auth/LoginService.php:327 +#: ../../../../lib/SP/Services/Auth/LoginService.php:330 msgid "Es necesaria su clave anterior" msgstr "Your previous password is needed" -#: ../../../../lib/SP/Services/Auth/LoginService.php:339 +#: ../../../../lib/SP/Services/Auth/LoginService.php:342 msgid "La clave maestra no ha sido guardada o es incorrecta" msgstr "The Master Password either is not saved or is wrong" -#: ../../../../lib/SP/Services/Auth/LoginService.php:451 -#: ../../../../lib/SP/Services/Auth/LoginService.php:514 -#: ../../../../lib/SP/Services/Auth/LoginService.php:560 -#: ../../../../lib/SP/Services/Auth/LoginService.php:603 +#: ../../../../lib/SP/Services/Auth/LoginService.php:455 +#: ../../../../lib/SP/Services/Auth/LoginService.php:518 +#: ../../../../lib/SP/Services/Auth/LoginService.php:564 +#: ../../../../lib/SP/Services/Auth/LoginService.php:607 #: ../../../modules/web/Controllers/AccountFileController.php:235 #: ../../../modules/web/Controllers/Helpers/Grid/CustomFieldGrid.php:108 #: ../../../modules/web/Controllers/Helpers/Grid/FileGrid.php:108 @@ -1207,22 +1235,22 @@ msgstr "The Master Password either is not saved or is wrong" msgid "Tipo" msgstr "Type" -#: ../../../../lib/SP/Services/Auth/LoginService.php:452 -#: ../../../../lib/SP/Services/Auth/LoginService.php:515 +#: ../../../../lib/SP/Services/Auth/LoginService.php:456 +#: ../../../../lib/SP/Services/Auth/LoginService.php:519 msgid "Servidor LDAP" msgstr "LDAP Server" -#: ../../../../lib/SP/Services/Auth/LoginService.php:471 -#: ../../../../lib/SP/Services/Auth/LoginService.php:476 +#: ../../../../lib/SP/Services/Auth/LoginService.php:475 +#: ../../../../lib/SP/Services/Auth/LoginService.php:480 msgid "Cuenta expirada" msgstr "Account expired" -#: ../../../../lib/SP/Services/Auth/LoginService.php:484 -#: ../../../../lib/SP/Services/Auth/LoginService.php:489 +#: ../../../../lib/SP/Services/Auth/LoginService.php:488 +#: ../../../../lib/SP/Services/Auth/LoginService.php:493 msgid "El usuario no tiene grupos asociados" msgstr "The user has no associated groups" -#: ../../../../lib/SP/Services/Auth/LoginService.php:605 +#: ../../../../lib/SP/Services/Auth/LoginService.php:609 #: ../../../modules/web/themes/material-blue/views/config/general-auth.inc:10 msgid "Autentificación" msgstr "Authentication" @@ -1503,16 +1531,16 @@ msgstr "Account imported" #: ../../../modules/api/Controllers/AccountController.php:72 #: ../../../modules/api/Controllers/AccountController.php:104 #: ../../../modules/api/Controllers/AccountController.php:140 -#: ../../../modules/api/Controllers/AccountController.php:186 -#: ../../../modules/api/Controllers/AccountController.php:236 -#: ../../../modules/api/Controllers/AccountController.php:311 -#: ../../../modules/web/Controllers/AccountController.php:225 -#: ../../../modules/web/Controllers/AccountController.php:720 -#: ../../../modules/web/Controllers/AccountController.php:765 -#: ../../../modules/web/Controllers/AccountController.php:806 -#: ../../../modules/web/Controllers/AccountController.php:845 -#: ../../../modules/web/Controllers/AccountController.php:895 -#: ../../../modules/web/Controllers/AccountController.php:929 +#: ../../../modules/api/Controllers/AccountController.php:190 +#: ../../../modules/api/Controllers/AccountController.php:241 +#: ../../../modules/api/Controllers/AccountController.php:316 +#: ../../../modules/web/Controllers/AccountController.php:224 +#: ../../../modules/web/Controllers/AccountController.php:719 +#: ../../../modules/web/Controllers/AccountController.php:764 +#: ../../../modules/web/Controllers/AccountController.php:805 +#: ../../../modules/web/Controllers/AccountController.php:844 +#: ../../../modules/web/Controllers/AccountController.php:894 +#: ../../../modules/web/Controllers/AccountController.php:928 #: ../../../modules/web/Controllers/AccountFileController.php:234 #: ../../../modules/web/Controllers/AccountHistoryManagerController.php:112 #: ../../../modules/web/Controllers/AccountHistoryManagerController.php:147 @@ -2119,7 +2147,7 @@ msgid "Enlace" msgstr "Link" #: ../../../../lib/SP/Services/User/UpdatedMasterPassException.php:45 -#: ../../../../lib/SP/Util/ErrorUtil.php:145 +#: ../../../../lib/SP/Util/ErrorUtil.php:155 #: ../../../modules/web/Controllers/ConfigEncryptionController.php:68 #: ../../../modules/web/Controllers/ConfigEncryptionController.php:142 #: ../../../modules/web/Controllers/Helpers/Account/AccountPasswordHelper.php:116 @@ -2286,12 +2314,12 @@ msgstr "Socket not initialized" msgid "Error al enviar datos" msgstr "Error while sending the data" -#: ../../../../lib/SP/Util/ErrorUtil.php:128 +#: ../../../../lib/SP/Util/ErrorUtil.php:138 msgid "Opción no disponible" msgstr "Option unavailable" -#: ../../../../lib/SP/Util/ErrorUtil.php:148 -#: ../../../../lib/SP/Util/ErrorUtil.php:155 +#: ../../../../lib/SP/Util/ErrorUtil.php:158 +#: ../../../../lib/SP/Util/ErrorUtil.php:165 msgid "Se ha producido una excepción" msgstr "An exception occured" @@ -2304,40 +2332,40 @@ msgid "Cuenta visualizada" msgstr "Account displayed" #: ../../../modules/api/Controllers/AccountController.php:102 -#: ../../../modules/web/Controllers/AccountController.php:554 -#: ../../../modules/web/Controllers/AccountController.php:610 +#: ../../../modules/web/Controllers/AccountController.php:553 +#: ../../../modules/web/Controllers/AccountController.php:609 msgid "Clave visualizada" msgstr "Password viewed" #: ../../../modules/api/Controllers/AccountController.php:138 #: ../../../modules/api/Controllers/AccountController.php:144 -#: ../../../modules/web/Controllers/AccountController.php:804 -#: ../../../modules/web/Controllers/AccountController.php:815 +#: ../../../modules/web/Controllers/AccountController.php:803 +#: ../../../modules/web/Controllers/AccountController.php:814 #: ../../../modules/web/Controllers/UserController.php:411 #: ../../../modules/web/Controllers/UserController.php:415 -#: ../../../modules/web/Controllers/UserPassResetController.php:186 -#: ../../../modules/web/Controllers/UserPassResetController.php:190 +#: ../../../modules/web/Controllers/UserPassResetController.php:189 +#: ../../../modules/web/Controllers/UserPassResetController.php:193 msgid "Clave actualizada" msgstr "Password updated" -#: ../../../modules/api/Controllers/AccountController.php:184 -#: ../../../modules/api/Controllers/AccountController.php:190 -#: ../../../modules/web/Controllers/AccountController.php:718 -#: ../../../modules/web/Controllers/AccountController.php:729 +#: ../../../modules/api/Controllers/AccountController.php:188 +#: ../../../modules/api/Controllers/AccountController.php:194 +#: ../../../modules/web/Controllers/AccountController.php:717 +#: ../../../modules/web/Controllers/AccountController.php:728 msgid "Cuenta creada" msgstr "Account added" -#: ../../../modules/api/Controllers/AccountController.php:234 -#: ../../../modules/api/Controllers/AccountController.php:240 -#: ../../../modules/web/Controllers/AccountController.php:763 -#: ../../../modules/web/Controllers/AccountController.php:774 +#: ../../../modules/api/Controllers/AccountController.php:239 +#: ../../../modules/api/Controllers/AccountController.php:245 +#: ../../../modules/web/Controllers/AccountController.php:762 +#: ../../../modules/web/Controllers/AccountController.php:773 msgid "Cuenta actualizada" msgstr "Account updated" -#: ../../../modules/api/Controllers/AccountController.php:309 -#: ../../../modules/api/Controllers/AccountController.php:315 -#: ../../../modules/web/Controllers/AccountController.php:893 -#: ../../../modules/web/Controllers/AccountController.php:898 +#: ../../../modules/api/Controllers/AccountController.php:314 +#: ../../../modules/api/Controllers/AccountController.php:320 +#: ../../../modules/web/Controllers/AccountController.php:892 +#: ../../../modules/web/Controllers/AccountController.php:897 #: ../../../modules/web/Controllers/AccountHistoryManagerController.php:110 #: ../../../modules/web/Controllers/AccountHistoryManagerController.php:115 #: ../../../modules/web/Controllers/AccountManagerController.php:145 @@ -2709,9 +2737,9 @@ msgstr "Group deleted" msgid "Es necesario actualizar" msgstr "Updating needed" -#: ../../../modules/web/Controllers/AccountController.php:149 -#: ../../../modules/web/Controllers/AccountController.php:204 -#: ../../../modules/web/Controllers/AccountController.php:474 +#: ../../../modules/web/Controllers/AccountController.php:148 +#: ../../../modules/web/Controllers/AccountController.php:203 +#: ../../../modules/web/Controllers/AccountController.php:473 #: ../../../modules/web/Controllers/Helpers/Account/AccountActionsHelper.php:60 #: ../../../modules/web/Controllers/Helpers/Account/AccountActionsHelper.php:61 #: ../../../modules/web/Controllers/Helpers/Grid/AccountGrid.php:159 @@ -2721,21 +2749,21 @@ msgstr "Updating needed" msgid "Detalles de Cuenta" msgstr "Account Details" -#: ../../../modules/web/Controllers/AccountController.php:223 +#: ../../../modules/web/Controllers/AccountController.php:222 msgid "Enlace visualizado" msgstr "Link viewed" -#: ../../../modules/web/Controllers/AccountController.php:224 -#: ../../../modules/web/Controllers/AccountController.php:555 -#: ../../../modules/web/Controllers/AccountController.php:611 -#: ../../../modules/web/Controllers/AccountController.php:650 -#: ../../../modules/web/Controllers/AccountController.php:684 -#: ../../../modules/web/Controllers/AccountController.php:719 -#: ../../../modules/web/Controllers/AccountController.php:764 -#: ../../../modules/web/Controllers/AccountController.php:805 -#: ../../../modules/web/Controllers/AccountController.php:844 -#: ../../../modules/web/Controllers/AccountController.php:894 -#: ../../../modules/web/Controllers/AccountController.php:928 +#: ../../../modules/web/Controllers/AccountController.php:223 +#: ../../../modules/web/Controllers/AccountController.php:554 +#: ../../../modules/web/Controllers/AccountController.php:610 +#: ../../../modules/web/Controllers/AccountController.php:649 +#: ../../../modules/web/Controllers/AccountController.php:683 +#: ../../../modules/web/Controllers/AccountController.php:718 +#: ../../../modules/web/Controllers/AccountController.php:763 +#: ../../../modules/web/Controllers/AccountController.php:804 +#: ../../../modules/web/Controllers/AccountController.php:843 +#: ../../../modules/web/Controllers/AccountController.php:893 +#: ../../../modules/web/Controllers/AccountController.php:927 #: ../../../modules/web/Controllers/AccountFileController.php:233 #: ../../../modules/web/Controllers/AccountHistoryManagerController.php:111 #: ../../../modules/web/Controllers/AccountHistoryManagerController.php:146 @@ -2749,24 +2777,24 @@ msgstr "Link viewed" msgid "Cuenta" msgstr "Account" -#: ../../../modules/web/Controllers/AccountController.php:226 +#: ../../../modules/web/Controllers/AccountController.php:225 msgid "Agente" msgstr "Agent" -#: ../../../modules/web/Controllers/AccountController.php:227 +#: ../../../modules/web/Controllers/AccountController.php:226 msgid "HTTPS" msgstr "HTTPS" #. (itstool) path: action/text -#: ../../../modules/web/Controllers/AccountController.php:256 -#: ../../../modules/web/Controllers/AccountController.php:300 -#: ../../../modules/web/Controllers/Helpers/LayoutHelper.php:278 +#: ../../../modules/web/Controllers/AccountController.php:255 +#: ../../../modules/web/Controllers/AccountController.php:299 +#: ../../../modules/web/Controllers/Helpers/LayoutHelper.php:280 #: ../../../config/actions.xml:157 msgid "Nueva Cuenta" msgstr "New Account" #. (itstool) path: action/text -#: ../../../modules/web/Controllers/AccountController.php:344 +#: ../../../modules/web/Controllers/AccountController.php:343 #: ../../../modules/web/Controllers/Helpers/Account/AccountActionsHelper.php:176 #: ../../../modules/web/Controllers/Helpers/Account/AccountActionsHelper.php:177 #: ../../../modules/web/themes/material-blue/views/account/linkedAccounts.inc:18 @@ -2775,7 +2803,7 @@ msgid "Editar Cuenta" msgstr "Edit Account" #. (itstool) path: action/text -#: ../../../modules/web/Controllers/AccountController.php:389 +#: ../../../modules/web/Controllers/AccountController.php:388 #: ../../../modules/web/Controllers/Helpers/Account/AccountActionsHelper.php:334 #: ../../../modules/web/Controllers/Helpers/Account/AccountActionsHelper.php:335 #: ../../../modules/web/Controllers/Helpers/Grid/AccountGrid.php:176 @@ -2787,26 +2815,26 @@ msgstr "Edit Account" msgid "Eliminar Cuenta" msgstr "Remove Account" -#: ../../../modules/web/Controllers/AccountController.php:432 +#: ../../../modules/web/Controllers/AccountController.php:431 #: ../../../modules/web/Controllers/Helpers/Account/AccountActionsHelper.php:155 #: ../../../modules/web/Controllers/Helpers/Account/AccountActionsHelper.php:156 msgid "Modificar Clave de Cuenta" msgstr "Edit Account Password" -#: ../../../modules/web/Controllers/AccountController.php:649 -#: ../../../modules/web/Controllers/AccountController.php:683 +#: ../../../modules/web/Controllers/AccountController.php:648 +#: ../../../modules/web/Controllers/AccountController.php:682 msgid "Clave copiada" msgstr "Password copied" -#: ../../../modules/web/Controllers/AccountController.php:843 -#: ../../../modules/web/Controllers/AccountController.php:854 +#: ../../../modules/web/Controllers/AccountController.php:842 +#: ../../../modules/web/Controllers/AccountController.php:853 #: ../../../modules/web/Controllers/AccountHistoryManagerController.php:145 #: ../../../modules/web/Controllers/AccountHistoryManagerController.php:150 msgid "Cuenta restaurada" msgstr "Account restored" -#: ../../../modules/web/Controllers/AccountController.php:879 -#: ../../../modules/web/Controllers/AccountController.php:882 +#: ../../../modules/web/Controllers/AccountController.php:878 +#: ../../../modules/web/Controllers/AccountController.php:881 #: ../../../modules/web/Controllers/AccountHistoryManagerController.php:99 #: ../../../modules/web/Controllers/AccountHistoryManagerController.php:102 #: ../../../modules/web/Controllers/AccountManagerController.php:131 @@ -2814,16 +2842,16 @@ msgstr "Account restored" msgid "Cuentas eliminadas" msgstr "Accounts removed" -#: ../../../modules/web/Controllers/AccountController.php:919 +#: ../../../modules/web/Controllers/AccountController.php:918 #: ../../../modules/web/Forms/NotificationForm.php:100 msgid "Es necesaria una descripción" msgstr "A description is needed" -#: ../../../modules/web/Controllers/AccountController.php:927 +#: ../../../modules/web/Controllers/AccountController.php:926 msgid "Solicitante" msgstr "Requester" -#: ../../../modules/web/Controllers/AccountController.php:930 +#: ../../../modules/web/Controllers/AccountController.php:929 #: ../../../modules/web/Controllers/Helpers/Grid/CategoryGrid.php:106 #: ../../../modules/web/Controllers/Helpers/Grid/ClientGrid.php:105 #: ../../../modules/web/Controllers/Helpers/Grid/EventlogGrid.php:105 @@ -2837,7 +2865,7 @@ msgstr "Requester" msgid "Descripción" msgstr "Description" -#: ../../../modules/web/Controllers/AccountController.php:943 +#: ../../../modules/web/Controllers/AccountController.php:942 msgid "Solicitud realizada" msgstr "Request done" @@ -3066,7 +3094,7 @@ msgid "Ey, esto es una DEMO!!" msgstr "Ey, this is a DEMO!!" #: ../../../modules/web/Controllers/ConfigBackupController.php:86 -#: ../../../modules/web/Controllers/UserPassResetController.php:173 +#: ../../../modules/web/Controllers/UserPassResetController.php:176 #: ../../../modules/web/Forms/AccountForm.php:135 #: ../../../modules/web/Forms/UserForm.php:161 msgid "Las claves no coinciden" @@ -3951,15 +3979,11 @@ msgid "Eliminar Notificación" msgstr "Delete Notification" #: ../../../modules/web/Controllers/Helpers/Grid/PluginGrid.php:89 -#: ../../../modules/web/Controllers/Helpers/LayoutHelper.php:334 +#: ../../../modules/web/Controllers/Helpers/LayoutHelper.php:336 #: ../../../modules/web/themes/material-blue/views/plugin/index.inc:1 msgid "Plugins" msgstr "Plugins" -#: ../../../modules/web/Controllers/Helpers/Grid/PluginGrid.php:101 -msgid "Plugin" -msgstr "Plugin" - #: ../../../modules/web/Controllers/Helpers/Grid/PluginGrid.php:118 msgid "No disponible" msgstr "Unavailable" @@ -3973,7 +3997,7 @@ msgstr "Search for Plugin" #. (itstool) path: action/text #: ../../../modules/web/Controllers/Helpers/Grid/PluginGrid.php:149 #: ../../../modules/web/Controllers/Helpers/Grid/PluginGrid.php:150 -#: ../../../modules/web/Controllers/PluginController.php:120 +#: ../../../modules/web/Controllers/PluginController.php:125 #: ../../../config/actions.xml:541 msgid "Ver Plugin" msgstr "View Plugin" @@ -4224,13 +4248,13 @@ msgstr "Edit Profile" msgid "Eliminar Perfil" msgstr "Delete Profile" -#: ../../../modules/web/Controllers/Helpers/LayoutHelper.php:265 +#: ../../../modules/web/Controllers/Helpers/LayoutHelper.php:267 #: ../../../modules/web/themes/material-blue/inc/Icons.php:58 msgid "Buscar" msgstr "Search" #. (itstool) path: action/text -#: ../../../modules/web/Controllers/Helpers/LayoutHelper.php:348 +#: ../../../modules/web/Controllers/Helpers/LayoutHelper.php:350 #: ../../../modules/web/themes/material-blue/inc/Icons.php:61 #: ../../../modules/web/themes/material-blue/views/config/ldap.inc:21 #: ../../../modules/web/themes/material-blue/views/itemshow/user_profile.inc:22 @@ -4282,15 +4306,15 @@ msgstr "Value created" msgid "Valor actualizado" msgstr "Value updated" -#: ../../../modules/web/Controllers/LoginController.php:101 +#: ../../../modules/web/Controllers/LoginController.php:119 msgid "Finalizar sesión" msgstr "Logout session" -#: ../../../modules/web/Controllers/LoginController.php:103 +#: ../../../modules/web/Controllers/LoginController.php:121 msgid "Tiempo inactivo" msgstr "Inactive time" -#: ../../../modules/web/Controllers/LoginController.php:104 +#: ../../../modules/web/Controllers/LoginController.php:122 msgid "Tiempo total" msgstr "Total time" @@ -4319,18 +4343,13 @@ msgstr "Notification created" msgid "Notificación actualizada" msgstr "Notification updated" -#: ../../../modules/web/Controllers/PluginController.php:181 -#: ../../../modules/web/Controllers/PluginController.php:184 +#: ../../../modules/web/Controllers/PluginController.php:188 +#: ../../../modules/web/Controllers/PluginController.php:191 msgid "Plugin habilitado" msgstr "Plugin enabled" -#: ../../../modules/web/Controllers/PluginController.php:206 -#: ../../../modules/web/Controllers/PluginController.php:209 -msgid "Plugin deshabilitado" -msgstr "Plugin disabled" - -#: ../../../modules/web/Controllers/PluginController.php:231 -#: ../../../modules/web/Controllers/PluginController.php:234 +#: ../../../modules/web/Controllers/PluginController.php:238 +#: ../../../modules/web/Controllers/PluginController.php:241 msgid "Plugin restablecido" msgstr "Plugin reset" @@ -4357,11 +4376,11 @@ msgstr "Link deleted" msgid "Enlace creado" msgstr "Link created" -#: ../../../modules/web/Controllers/StatusController.php:94 +#: ../../../modules/web/Controllers/StatusController.php:93 msgid "Versión no disponible" msgstr "Version unavailable" -#: ../../../modules/web/Controllers/StatusController.php:142 +#: ../../../modules/web/Controllers/StatusController.php:140 msgid "Notificaciones no disponibles" msgstr "Notifications not available" @@ -4467,7 +4486,7 @@ msgstr "Request sent" msgid "En breve recibirá un correo para completar la solicitud." msgstr "You will receive an email to complete the request shortly." -#: ../../../modules/web/Controllers/UserPassResetController.php:169 +#: ../../../modules/web/Controllers/UserPassResetController.php:172 #: ../../../modules/web/Forms/AuthTokenForm.php:101 #: ../../../modules/web/Forms/UserForm.php:157 msgid "La clave no puede estar en blanco" @@ -4501,7 +4520,7 @@ msgstr "View Profile" msgid "Preferencias actualizadas" msgstr "Preferences updated" -#: ../../../modules/web/Controllers/UserSettingsManagerController.php:89 +#: ../../../modules/web/Controllers/UserSettingsManagerController.php:92 msgid "Preferencias" msgstr "Preferences" diff --git a/app/locales/en_US/LC_MESSAGES/messages.mo b/app/locales/en_US/LC_MESSAGES/messages.mo index eb83bf9ee96943d077b57745a5c31cfe81c101ba..9b1e1e80f89cc480394a4bac841c05bc73c3b51c 100644 GIT binary patch delta 30338 zcmZYH1(;Rk{`T=b#0)WX4mmUfGeZvD-Q7K;bT_zY1nCY5rMp8yDJe+>L_!4wL`p)W zeZTj9et7Xe@4Bw#=jmQ+ZP0VBY!AG(Gtm1bX{^~kuKuxozI1pbx6fBS$mi?USgAhW zyna4kRh*A0@D?V;S4c5maDSgK1e0STjKpME3YA|ElVCGUf!$E~qmX>hH-|uC5*A}x z+=SKfdsIiM2Dpm3Fg@`ym=arIR_u>CZ~2%w1a%U1Q>yuKyg$%H83M~z(5>}EUs@7X2Th% zes*IJ{rfHwP=nVoH9khoJkDV22-QJ^#Yh1+7>tuq16?qT_1B^Lk_2`9EvmuOSQLLn4KQT5YakqzUlP?oZPZFMLUq^y)j@wu zgQHO87oo~+LiO{F#ZP&ba20hb@1YvAfw%OA1yP{?~$l?=F z_2*c81?DHd6(i8QO(2RuGFC!+T^02>^|1IHR0Df4E}lenZ~=98ZlhM{6~@Hi5pJsz zqn17=YQ}j{hr1MNf{l^0;Q2Zc&=Pe=&Co*?n1t%!3)E@fj4F2&b($}up645=m3x57 zk2%tDmrW|$4N zG6hf_R6uQ2b5#9as6*_b20B;Lzi$lzEzw?7hbK@o{uwjkV~Zym?Up(lW+J@^X2xcy znGHwPpMznz5)0rt%#N|fxThmGs(eNCG@@1nH1h#gU?%DeY(V8-M2+|%YES<~ZB5Wv zH?y>;{9I-UvleP1ZBXS0ptf$J#b=IX{bQ4`iiCW)0rkfE6}7kbQHSmY>bdrf<57b& zs2TLeo;VRh@inTQwBy~(YhoedBQXo^#!$S5dGXzN*1s@;$j{uKc0?Ws-xySfF(My|3xB+#>9-;>R1~m~c@g(;q%Yl0QB2hCc zj;hcEb$UBuAofQ!FwD}YqXxbdgK!JR#;;L(|1D|-E~4t)Lmle($N)WGhRNMf$(R6_TKY!RN`7ncv#5H%p$_NYsCq$D+(6Ty|M|~MKm{XF zOI;p|U^M!d(Aa7f#$V%S*%XHK32meSOfn=y={Gkr}=zU za3reZlc<6*r@NnCwXhiRd6)=)L=EH?#=?Iv3BJX+m~e(0Kx$Na7zSf;)C8-bwzwmD zI!vPpXsN%z1h~ySh^lxN)!{XZ|7H2_Fb?VQXS$V2j(SRRpq`$p7=`Vy5YETEcn;N1 zz%2G(BS|#NjWis!w52cu)<+GX5Bg6lCL=xvb=cOT&dgR!j$fn7pFw?oucB7qg{8-t z?aHMz|N7SrRm&I+oE2wbcDl4UWa+I0IE~6(+_VsQO1y0+9qFP#v_uQ0$Fb${E-Ox1$bQin*@gC`>`T2Ij)H*c2yY4!nzD zm}s7Bw0$Z( zQ02#=R$>;W!F^a1e?opn`jRa4`C8MzZ!!T@c!+w1zCq0(@C&zusZocl9BM#SQ3Gg# zs`m+MW&`TH&X9P04iK>zpuo)vh5p=2anVr zl&+|~--UWwZeltNSnTuV!3-FRwJ<&QM4f@jm;twYhKouXL4qeO}qgX!Vy>ycVTvXfFYRdOV(cnBffMUHbwoS8Gt&y z^DTZDGZDXo`i{r>${n_F%t*WGe~6;=MZU8%&?fqB`#|5Yf9Yd}76I6S_-U@yq z69_{k)I$~MiCWr;m>E}E{t46o?x4#3iz=69rHdEBNaA%-GaZ4UxD-|HAgaCVs1@~m ztK1ATqefZ=vtoDDA(??1*cQ}Qow4-SsFev>?eYtw$~Q3kqVi{0d^6@Ge%8`oA`|g^ zDc88Y%7dC&Rn*eA#k@EKwWRA%OMJ+@jGE~q)J)T_b(X|1;w@1V8jqUscFcx9q5sfg zIz9g(>)fF#ggP|MPy^_P>R=LTsrF(nypCBg&U&}x;h3FxW%Tbos{UBiW4H*_;c3*0 z+(We&w1IN;?+YWKj?1DNYHp4~HMqt+fLh|8P>1UUMqvDnuEV03fOuUD#nxB=M_B%L z3?hCC^*CNYPa}-GiBB#T#rQY~)zKK#0G6Rn`ySK`9-w9zZ!?3&%&5I>kA-kDY735F zBtA0JZ*ga+28NS9XbbDFQ@nx%9kK(cJ-%)}GvjV`hcY8-=_+6-c0}#%c+?qKYw0IZ z|md<5DvmmQD@;F ztd41Sx<6ib!ji-nU@N?g<+1QCe$3!d%#V*e0zC+1+U=Hj8mi$#s4Xe}wR`su!D!+m zu^isQJeYlt`;FKLixOXoE$|9zriJ&qk5vs!O1y>H)AU9WNJ++QRE6~z7Y|zedkiH0 z8|v`f#bA7lIwNmU_0#TizYp@GI;wwq;co}Nu zJ25sMK+W_h#={>m5&nWH@DV1%Sl_zz)To)}#DrMXtb$31H%6^wXH-AElt zNeQ^mJcFr;|Ay-D6>3Qn9dKKb6*a(c)XEgal2`||Ra4A4sQksK72Sb4E2q(mLm=p& zTcX66fp|Eoqw1&uwL#6ikHtr!W;)B_D=?J!E>ykCs16^Ze}xXY38Y4?bR=fPvWHlI zRfr}bGY&uvU_NHT-KY^?L6v)oYB1=qGc9Um@}L^7h$`2_?2cOUQK&7QfSSlu)Wnt? z_S_O~AwkdYH&!6t5!XQ)RKZBI464C;7H^9Ah<8OT`6ARCZw2a*UO;vH9yPF7-?>+B z2-YQD%Og;nz*20A*HG{DLPyn2UNK{$J`!Hz*fW$qYi22h2C5XtVS*M*Qg~ukJ`h#s6+T3Gh?a~Ztsd=EaJ^jTh$uX;YbX{ zg;)UhVPX6W<6_Q}ZlL)whMxbDF5oMJI?d%#BddcNc{G;5VW_X$*QkLW!=m^rYDOX7 zyN_2+)E*baK&*h;!s@62wnX(a(4Wr!k0GEL&M`M(F5<^g9X&(sUHnt-=XfZpfiToS z3z?Ns9XG*X`~=luf7Ae{q7Lt3b1NpMf8S988sSe^1n*&P%zWDYVyT7YiTA^*xEuAR zi*d$1Eg3OA@lvP`TcGxO0BT}0P>EQH@dORJ$8FgTXhai|X0VH6%kb^I2?F!TraIj@EViSNV+ypKApAwTk0@mTyv)_;;RNYLI4 zy1+LZCt-HXanb$tS}iO?d?u#A3#f+vL=7nTk~=f`us-n?SPwU2D8~HBtz=fz7L~x7 z*vKPLiNJEqhxbvZHvMJyLdlAWh=*fREP;CLYFl~()JnC-*w`2Km<>j)&}h_SyBKw- z4`O0`fSQ2!j)3+ybD|2i!W=jOtKb&%HAWIIf5nyWgL;9jMy3Cb8gR0!?y1Rw z35XZLcvuNTur6{4JzrM>n%N*sjh~|`EXO3c)#696I`JP+?}H52+!8m(a>O^H>ODc7 z?td{Q248nun+4TgVbm5@#Z>g~YfT`Cgn^hIJyd~37!$W4Zz|s|)Y9(32t0yX@~5bo zy)j?XMV z^rm}3RmM=#yQA8hf*o)-Y6UXfa`kgzHsUogJ@&oD`YU0&CG0XUqGs?6HK4S=yFHCU zy^70W32cnYpM_evjhGgHM%Ditb*9qawy!Fx+COI#jDr1Nj=&@sF4a-=NM?vb*ka3^OaB+G*_(P(!^?Pr+o%Sc+)Z#l)hj1Tipx>ib!n;jCk4?;bE+YwQ ziF2c7P{!g-%H_dpcJAYK&XU&4Ob^|Nd!RZPi#i+gQCqX#(hs5zc-ZbQw}d@VD>MnUlr3ujW)US>eeASQqU$V`vgnog*Wdtr7QfuXnxQ{iz` z{ogPy{$uF@FWtaHP)|_=s$5mn0NWrF_k2SLXipcR3a&?u{5Wca7ceQ_L3Qv7{fFz7 zd!Cb{9=AfM{JN;K(;RhZJEA%sXD-6L#J6J{J^!}}#3JDl>iK?#TKX554c}rL%>3Ft zZlf_j@vm?KUc{={`i=Vo$r{wk-9ioM0crp*P+OVct&3;EWc2SVLO?UDfyuEoYLEJ% zR$!v}1*+Ue^B}6h3#fX3pvu3)P)zjB4J0q7Azl=9_!?jYwna}%KaGGIUSe*=4#dAh zy$^D~cYko0hlPosMQu^gzwSkn4Ao9U)Ii#!R&X$C<{s({%|X>$iCUSh|FZt62<#&v z6JD^47nqJX?=b(2(xYaY2h~7%)C_8)1~eSCr#nzHyn|`+Ii|+M0RjFuVi*P!kH98a zEWiu!|B#qTg7*3xhT{v=W0NIDfd3HXMm1O+wUnJO2aZAwd@X85r%(gDgj#`{7XJga zLeEhHiWxJ&zcT4O0-9L?)Dl%jjj%Cl0PRsr*bQ|^N26BeGt_`qpc*`gA$SG#m_A1h zG;OQ^{|l-RYCsK8{WU{vx!1!IMxtIIvr&)N7pRZO2GnWZf*Q~siyuNA((lb1n34ED zsE$*`b_36k>ZmG~#}?*NWWb*9cLM6*J!%Pq0$syNP%DxHHR8fp0;{8*@6S*j&P1)y zHY|rHQ3Fp9_x`RK z7|-QrLk*}1>h#w~9l~hT`=C4OOnIm?G70t6twc|I{S5&frn9IS-$xDP4XR+G_^zWI zsPtl}C9Z|qih8IHTcSGbjM~bfsQP13E4s+i*Q3hsj340n8#qLQMtB;vmsd~~pP)L3 z8|*qxjw+WEHPa|mN98SE6E%S5sCwPaL6$!n)$w#xy+y%1|62N0B&g%fs2Lu!_*GPe zr>FtFM{P;U1a8U0Fr0V=EQGzW0Io*0dkxjzZPfeam6)gYgW`DE{57_ueKFvZT2vS zV|zY_lTeSeTACX7KgOjhW2tQC`#*6hqCllBG9Am2Zcd(Qs79GcW>Iq6T;YHNb1A0X;{x^9JMU`A?YK zEq!X#W0VKgU^P_1)~EsWK|Lj(q7K;t)XdhSX1*7-g(px0`wjKVeT~`@Ukbf&_^pBJ zCmY7n^IwL5PIX081NBgQ)7jDoqfYZUi%&;&ycjj(4XF3RK~%%Pp$7a0bqIq}x`8A{ zrKd#I&y1c%o{xYmjoRy)sF_d0P+W%U=!m6XM*n*P)zBN%ip5Li4rNAEdRA1u0;u*X zqqd+Ks=w$|Jpan*NrGlR$};AoPU|XE1N$w09@WuZ)ZV^D4J1}-*Ku;xQxbw&vHYl| zFNr#QWzqkpMGd5RYMy^})YdWvp_XVQM&e}D*6cG+pgO#SYT%B=AEG*VXC@4Bhb|*( z0)NGz_H58P_l}m%l4@a#~NsHG* zwcpO-eX$7fF<1b-{RGMrc!FUVl{UctmrkuQvkIaHvS#LZ^ZXU6!EaFm{lVfl zQP2P1sI5wr!IjH_s#nb7jnV)2|6K^EfuTyk&n^B1YAM%S{5#Z2T|{+o3-v;JhdRU| z8D0H6n3Z@L)Q{5+s2?KZQ3G0mD!(5+HT0upJVfnL?9c%JUr3}wy-+Hm2G|C*^u179 zF%b21j6Ms-jT zb$T0Hd>S?({uOG5Z&2Tkkj&0Xn3s5848`S`1HZ#ae3;pDzs=HRaZ6nVhmsME+S}`> zCI1WcSiMKBP_nG3*i~mip9?E29gN1RasH_xl!%6MIG|qsD8b%1oT5<4r-6 zjYl;w4K>qwsF|)t9nu4+8CS-d%_zwQ{U=YN0| z7>(*^78b;fmVOJ>&~q~|%ypa^HM8uf4vV2yq&jLv8lfiA4vS%5EQuSjC_cb^`u=Cn z9K!nN33tXg+F%)}r35yHSVq2x{Oz zqo+N3NI*06g}VllnrTs6k`>iqIO>oUN6oaN<<~*YvkwOj@GeRQ<3Set~+!{eyb$Q{;8#!%*Tiu@v^O^bM$Y z{|QvP_bnbXpL=0tLv5{BihxE|3AGY6QHP`{YUDjohh->gkEf!xXbEZsHlXV5LoMxb z)Jj}MmA`{(=LM>K%>1ssq)6QJWhbD5QK+S_h-$DAs$yG<_q6y>R70Pk4%uAPH)5aV zA3_b_Eat;2s25sr0rynpz|V=d#U^_G9}!T6$_3q?)I$xZ1?t`24Ry%Iq6Rk6oP!$R zSLP;jpLqf`&`YR#w^1wm1U2BmDC+C^4fW% z!|9g37uDcR)K&x*aRbPWDqjuNUSG_OvoSj!L>=Nkitzkv2C<5|hH{}Q*1}vk5JT}R zR0D@m4L(Ml>LkTnei$mf8mhf+s2R^dt;kl?M9-rJ{Mh2jiu3%dV!q<;=Wu;g!SSdS zS%LZ$diEr7VlH;RBpxXdz+ zp(@-(4J5Ffn{fnc#?>wU2^Jte4t3i1peFDKYN->Kcj?7Z1L}-wZwhLlJ1|tw|4#(8 z1uy*xjI@FqVQEwctx*Gk2{oaHr~wZ}b-We> z@hIwPI*p!A=PLq*F?$vFf@y`J#5<$jgcDIqy8!jr9kTQ*sGsA1q6U(ss%xhrDn1<5 z{u1+)rN1)MR^$2CQk1ObJ__|wACXR|&+QO%66&kC7&Y@97C&k68y0_odSxf5?v^+^ z>f=?ytb_W-v`4kmzq;oF6G>=7!V;{5FR>q1tr6h=_k7==W|XjIfUgYZ#SYjTwbVah zS$v23=#;Kye;J_3V@dy@$0<1^n}h5Fd+umXE9 zHt}QVABcGYwN+P9OZf=3Wiji!^c1KLbE3{rVN0)!dNVddK4$#>C!j+$0=38UP^W(r z>TFy>4e$Y~qt~d@o2Y?{7e_swbx`f}L!I_X7GI5eY7SWZ3WgGYiV5}nCu`^qMP}4e z6+o>(NsN!>kdgXop_Z&EY9JlWp{M~)GZ&ld%{{0?cpSBY*HHc3LjU*wApyOyUZa*Q zTO(&d)Do9RHPFcHf@>lcIdW-(Yu8E6hM{Q+cRQXz{Gtd^*P9M~kjA_F2 zuLc%d!Y0%}PM{jRiyDZpsT)X2RD-!u^-7}}u7hg0jpg^T{Bfw2nu|Kbi%}C^j@q(K zO?m#cg!@S-fhQ~@u$gN(IjUe*)ZXVuHCP(8Rh3X%*AR7PMqm_<#r(Jz)$t?Liap0j z3~KIv!WHreC}9}txn75A@Fs?1f)?%@PzoyD3(H7L3@)&9b z?x8+n=~}x1mM|+|3_brfT)WvuE&gGZHP~xpoAE6Pb72b{h|NZ|F0vg#h)ZRZrjra{}Pvf_DdzT5-K^W@AQUg`5 zA?kVVgxa!^s6)H}^-=o{v*IJnj>$SWi*?}n*XfTYL5FD?Y6)kf2C@wG=GttYLe1isYl^;7K-Y5+G-FRXwrZizEuP2y#+22Me>a}{-_-kGVpx-Bi>S)e~^2D?xz zaTE38xQkkeho~)iZTa!KxkH!;^;D!mmCtJFxlk(^g*x@+Q3Gv;+WSGMmG#CD(5YUE zQMd}T;dRtf$L#KYh~&Vs#5~4W`d>9Kqlt- zRuj+*W(Vqxbrd!7E2zio4^+i}usHg9y1$+)fqE16#?tsTYNcM8fxTRN$x!X*K($u{ z^|)8YH2VHGBcK)NkNVmTvjWpGCh_ISo65HuwbbiSE3gB#3JSZARNCyt-uLX$G@0wQRUL~bI)^0)Id6-2Jktm z!L_If9K#lP7qtQv`n$)p9)=Mgf|}6s{yhJBL7XH(4Lw86B66IWXx!x7Wo`6RD1RF||SE4?%6sSE&B>4CMLO3*u)Iv~&puxzBNN)MMBM zb&7kUUL0dlhioybgLSCWeE?PNlz9_1;FqYw8#vf?oCuYk19fJiJOVn6Wl#;(w~W@P zj=EU-K+H{iG-?Glq23oqQLoe|sP{waA?{G-M9nnP;+0Sx*FX)l8Tz09UIf(9B-D)N zn;Xr;sK@d$>RtZ;HGuc1rzXWvm!1yQP9&;)anzZpjha|D48lRE$8iMmGGksU*QCNHC27>S3w_drI}^P2_LVRqC2@}O3xq@~wJos}l28TUrDI~cXq6U{|Z z&;MoudTb7(UJSQT6*7J529O`Mv}IB0wanJ2CGLfq(PVQL>czDX`{EKTg2_1SHL!*q z`uXT}AmKCtJq`s%xIcW>LoMZc)J%4wmhdcU2DecId5M}~+>vgplAu;3lg0C(R;IMY z>!MaJ8dbl`NS=S~=};2165~-L3>xJMHb8aI5;emPs1CZJ&c+Z_LlaS3wGcJHwU)jg zwQ^@r?Oa8byM^8G=_qF2pFr!;?#*-&a}xg-HL#px+-WXoRzY>x0`+R`Zs}`KhjKq^ zhQ}@aJk}?E8#REUW8I3BMLnMNJqvV2H82|WQJG@SLXCIP$qTwyp~1!KUc{?|&x{(9+F7JvMXw85}0eMtnKyjGRPu zRAz#EoElIzh8jSB)E0b(n!p^zb?R3V&{A$kt;Au}lAkfJ zpjO}xs)1*y@&TW_a*0v-=`0?GTFEHXiqt|KwuYA99di>OjGij4AfP?kidv#0*bFaX z2h2Ok{Wl_WumJHZsDUP&?4E)URJ!_YG7U*Wch1Q9q&N@(}CLBo0fkE2NHieh3CHv zfi6?sVOod!0rEX+29Hqj?19s$kh0BVU&p_cLrYKd;69+!ux1_P$M0R^HONQcVLhuXr5sHdVas-uCZflfpX za1HA4Z9)ym`_>Z9pbpC~sEW5yOZF0Vir=CJ6nln?CqQ+W64hW%)RGrLouS&O3AM3! z4=hI9!zkQ?Ou+N~MZn+iOlJbrlBPh7FcLMOl2{7spq6wh>R0Z3)aQFI>M^{C8hGki zZpG4}+R234n!K1DOJY)eb=niqk_|*1rn%^U3{f4OL2c1xi~o+A`6JW}eY0J|2~i!T zwRkSfO1v=Yo6^GKV=aFzrquJli-7j#464BksMCKFHS^b47Zc2J4Yo$D&=}M}7NN>- zLM{C<)RtXFwRgjOj4JmIwN)wR^8BlTZ~{swg{sgHwWsYY-WN5qk>)hiVO)Y*(&ea? z+JYMJUepSnLAC!gs@?nME7Xbx&Exr31IgyOhC)%NIs#R(9ID|4sF}4w&8#PCK!Z>n zjYqXJ166N{#kZh3`UX}0B&xliQ3JX)kLOQKj6;M$Fcp~TapURN)-#we(9+kK-oPQtw2q zz+TjhPFeb8)J(3U26`X;k1eYFThs&-EOaZA3ROQ0mF`7ZLTR(Q*%$*T@Zow+tACL& z84Ge+SE(1SiWtraFA<)E$1HsyWm^&-;4kI#{ia#i)k&w_U7l|!1xFEy9fOn1t*ak} z7jswT-a-84N0n<6K1V0@xWA`-L*lQkp1(5x$Y}BXgha_-aEz|7Gd@DOdV`%IM{lm9%ZN(~I(ZiPyCyu1UBr zX-TXdj)VXIK{G4u=)ig-$>>WY4HhM#4tFsc(iMloa|wUpqQ0}H2%>ym^3M~lXN@cU zG-=apGCvcZO4>$c*mak*lH9sR#N_=OgTg#5zI9e9C5_c0ypgoUme$1_&tUjm_)1Y` zB5C8eb&7Qrw?QkMhVvK;h zJk=U{N?gyiu4wKV{tzD*Yh)RX-yj^1fo3M}65-s0S6luLbB_(;3GL=5zcqeJ+u?+D z>HFjVy+4G4WeG2^iiIh3#s;G@*-5{~t#5b$d1Ek@HIk0Hl_>j%3feUj&r?pXNx`-h)O84d!UoukJDfaSdAP4ob`4giUIy+D z*AfER=p?n$Df7}YRuHbwy_h!s_79Hv-zE}G!I?DPl1yD$xyzEannG7d*Hwowzr1~m z2zMv^9d};JZ@2t!h&SPWPkutmO(bu+!sM?*UAG8lB0ZJ$^WGzH&l*^6cEc5}y#Jqd zDDxu?ez@MKkq;3Zp*Fa?a3`kRIQ($Ev3dunbIKAs;sXY%%d5vfT9G+}J28o0;h*?7 z>HOsL#igWBGw1jI(Zhc<)9pNiZIFhigtmKcUZWb5y-6yPT zH|4fct`A0Yx8W|wT~PghZiQS?{zEbb)0VpzjeS90Ey7(0cd&AkiJ#*BgLp+6`Gar~ zD%T*~gYYdJY>jQA%xMdsCa*HLt_-Hl-~A6y^lHOWM*IsumS1aNozsbbA;OwZff;%5#MRy;+TLtA@y{*^(XL-LfvS%ESW2Eb}qFp12cOhH>dvGVA+%xJ_rtEv-dx@{r^Ph}J zP8&^X!p|wR^Fu4Bzh==d8(saVT$KC{Rz8%prljeLN!`)p<>&r~cprZ%f0<2uDB&4& zIDj%!2$!OMdD8!l!TbY=#OJO+0bNlJ-(3nPA$>0XL1A4fDbvTwt)OH69O(`KRFd)~DbHW?`Ra3TC2tq;6!;fr$} z1ef45DlYI>|wMUzwZFnK%ZcpzmzzBZ~ZcYvh_TSqFBfHroK-qO-e=x_agBC)PD zewfVGG~AGQeJZ4~ksq_hhLg6J@M!Eq-bMzHfwB+r!&Q*{1xxyj$6@4v3TL@rRUy^U-TjZ`B(nDktv@%M%PD}%%L!W#XNhI(prKmT}C=)fIKAzhzQF`CT2sOvd- zx>6H=NBSMg)gYc1*OIo-8s2OkqI`D?PbYt-wR7IusYJX4^~aIL);|T6S7S#KUU63;oQ1SFc!SFPdk9~!HAs@L`$vt;BEE~V|Kdv2b%gwb zF6hfb_#f`?slSi5*OSiQMfRa0zRCGi63o_Kr0gVfoAPZ!4pu7!2Ss zW#3X(f3zQ~MD;&~gg@~t4aCFF+%LFw^`X)Q^5b*gAl`y9{b}S8@qewuKk1|}@n__x z<}PRHIjB2=vbs8wc9e4MiQgmKhVm^5`{(~Ffeb9e7a~gj~y_nW!3Bo%FFGpRg zD97db|F2UjQn(5kll*D?d5_F*2HR>%Idnt;06(XZgH2&`j4Z+Hey@xlyy>o#&k_3tvwZ{S))pe zAg>VRwh%r~qX8e~DPPxm@_Uk}Ym!;b$}PgVr2WG^H5U6H&kDHW?5hQ;Qm_!6%_08* z;aj8!;#Uml2f}T+)7yYmWhr^TaO?Vl1E^Pq}~R{%|!RzZrQC@FjK5k&%da zR{j2~#;vOr8D+UExTr6T^h8wHVEOq8A0RxOdpu>b&_E{cyTreyvje0h<^Ga#x)M43 z|7=1zT|Zk}3a25>|NJZR=SQP0&mf8uUxg7LrSG9!PSSLxq?0m)dt1Z336G_0V(TEQ zm3vCr$D}>r{>$=OQ?3;C+v?AMbx9m(g@3{gWQ?TJx1=}Xu0dLR;;}KpW=7Q4LI2>Y z$pG?M!-L7cPvc*beuD63oQkios+A$=ze>^GX6^qEWW=SCt`amh+`=w}Wu#ya(jvM4 zvgTgQEq{NvoZViHeHIIayk7X8fUzDV8}OZz_!EwqZN{51uN*wUt= zp+Ih3#Yq1RhjA~b{Cv`{k~YHfa}zFTVT$-l(_vlGK3xBh*NMBUwe9U8Qk}bz6-ta3 zXt*19LTYs(uPBA95e^}37v`YR&#c9wqupqLDEN%KJQ-WCFdg%6%KTSN%Jkvh!JU~rT@|sf4ZI2QWZV_V zuRxu2s4FL(w&&K>ob=>`myvgoa0~7%9{+ekL$xsph4z!#m3Rck=YB(2?}+UFCityL zyd!0GCAEehk>8ntd{0_!JWBfKlzBk>tn!GzqTY5@;%d&Fin}Rgz0(x9PJz}$W)W^l z#w`jbAiRM_o|4ysv~0w~@d@`^@=ua}leAfc-%~CY@%-dn<4$P7i3WZnP1hPMMEYzx`1pEET5QtFaqp*m zX3LL5`NB2;mET7CbkZK_`#+0FF-D~;0Sz3r4##0QdCf>KPvsJX?<${gPs*RPa-lS| zoA5WJ_a>aw(z}@x{Vnsl#eZodDRqze z8v{Q4{ZAGWbgi>ST#P@#P^bWv=Wrh-aRBiH+`7^++hK&OP-hnRB+Aqw?Fea6w08p^ zS=kBX|43Q`;!UZ0n0pKHd;zhxmFjnGcx1ciKAoc5_w?22*1uEd9--|!^!+5dZRc*C z`+c0)xo@wYJvz7T)?sFjr|ILh|1Y|&=+pLTLwdQYJ$i<=>)E|mbUzgg&6%xl*sf^_ z0_Fw;Muq0hUo2{FM52Jq7T(n`Q9zeIRlD_!Zr`E(e_eO(8%@ps;?V=5J9kschXNgX r{Ga^(J^m}P>(a=8QK>T990qjg)3GS1ms8pY? zbRVCu3YNhjoPddOF;dL86;t9KOn{d#2|lp=515E}l)kQhQdE9+q`v1XNgyE!6)`n7 z#H!dE)zN+o!gH7wA7V0$(a+}#!L%5PWibL~94liLGe1pl**Ixtne7@ua zQVR6jE@ zIj%xa1rHENiWjjKK0-BIY>;cX0j4BA7&VaT7>FxSE3*wXpu?yc|A{Jh2i4Il%a1$Q ztwaV?e&}GZib zN3~Z0RjwhbpAHu9<5|K;)Tx||YG|dU??hERf*Scn)Qa4({C8&bVJ<%jYM{Xu&xfjC z(&E)IKk+7*3%!X1!U*g}U8fhQ>y(U@QM@FofwmYMd!ahe%IWM(M6J+bjEY-PTeTDQ zeK>=f@fA#g4^R{Qf^4DZOYps0q9D`^Ls10^qB?9tr%)^N zC#tQk5jZ(&A^GSbZ~ zGpc?`%!W0v01m(`xE6KG&ZAc1AM`Y$7^B?G)1e9!L!E*8sQjU*5l=_$=`X0Q*??M^ z2+Kcb-ZS5#CK7A3E1wRvb@?q`Y&7eyrLIXrKCF-WVvR-Z?NrpETYwtaN^F1!Q8P$6 z#^>vf`7s!mpxTK*&HN1(!fa#RZ$m2#CO!)D;_|Vqe_;ZbNYI`Jj`R7r0KS~44%eV& zco?c?0FWB+7JXx2x~q$8^Q5Y$X2TYM9$qa&ylxnl9Zu`2P8_zhN?FM#F`e2$x}O+>QzHS4%&O@rd6=P4GEt zivy>y{yI!K2xzIxV|;9Cc0yI`kLqxg#b;Uma@5vs!Nj-+bxTg8ZqEx0!?;u3H7tX9 zi4Q>avuY~)uaWE^ArW3cE$stLhaXV`NHxt3FcgyzFNxa2I;b<#1e0QGRQZ0W>opS9 z?gC5Sh)Id>MNRnJG}b?mz~3ZjMDHyl#&oyTX;BU4LRAb$m8*$b;^wIO-B9I*VqE+I z)xiu@`E{s)?nbTHLDW{A@Cf84a1qr(v>EOTl@hg-;n)hBp$^+#OorDn2w!7%j5Cv~ zhhZ3slQ0|ZK(%`tL+~wX#Z%961MrFv(1^;SW>gi`K{M3MdZQ|gKrQ`3RJkpv>vqVz zfGLRILoNA#W`fzSoeZcmk{8u}Ii$YlYhnqVt-x?p2h&gkSdLo4t*C|%qB_2S`S2d< zgOhBI%TI$UpBuFj#W5AO!=mURe;)dFVN3e=h0S#prlUTgOHm!IM=jy6sJ(lH8qf>W z0DSXYy@aTlrL%ZG)C5YQmcEwdx3}~GsKYxR{lEW{t-w+YCSyD5o?b?6%^TDJKBHz9 zeZKpkBth+cOVn-o0n^|r%!5ZT7~f)AOuoRKfiP70Cg^Et1`<%kX{bZD$>QfRGx6sb zhRGJX4y$1<;{7o-F2`UzfGP0~=D<%_2(vEY&pB*~S#TPv-0nrJzY1O?K?4X_?Ea!j zhg$kF7Vm-?i2sC{a3kulUBLAC4{C<-m$(7vKy^?XlVcZD`H`sd^DKYQ63;b!iG%`V zyhmNDoJ(EBvZ#iepawVq)zEa*;aiVt@D{3`Z<#yY$xwTr3v*&w)P%aDR(v+9y{#UB ztOU+l!Urpme7RfN{Fssa8mJ0AQ3Lo1)zB}fEjVcL8>sKezo>y_UE#K-GOAoBRC}W_ z19~e7Xokm8BYlV=81#!fB;lxz8>6nR=zm565(rYlNC;e@kD4 zOvLl;BcQ#y>=Jx0P^Lx}xXP{8mh6`PD|Zv!T$f8SXG>iBO|Ls8c`v!fcUZFWR0rH49P3osXML9N(rjF10fFveW( z4s}*kelv`TeNfkN2znafCITh#Hpa!^4X&e{r~y<(o%S}U8B9YpxEagfamXx9hcO57*O(K7H?jU&!s?scA?t|RTo6A>uybP%uBohropl39~i2=2uzJPEdBv?eS`MtXP*5pN2q$Dj`B4AhL*TKcb;koXzYfNz`6F%j`EsFh5#-}RFM{lEVi31}}1 zDgoP>{V)abai|U#qn30BYAa5n26zFrGPkh=zPJ2Bzq)cIQTY{7E7}}&R{EkBi@*i~ zTB4np4lkfOdW9NLtOIW5sZjCksF@bGcy$aW-V#;sdsK(h(Z52d3H*v$=}VX%|31L_ zt3vF9?hK?u4WJBWz*eXck3f~1gKBVt8G&l}GOFQ!Q006P&LGs1XGd*mKGYT#Mopwr zgy)v9F$ucA9jw4+R7VG`;3e}Rs=*Hy4>;tmZ4%U$RKVO=9d$^DpgLZG8rWJahzGDX zzV!$cBT)IU`}=(q<|2Lrt6;n%?zA?*X2b_!W4w&o!+b~G2c`?^kRC@J;)|FPZ=!C& zzo;!v`kOnPc~M*Fm9juB)Ka%bE$Kki9!^3X!WEbi_oMdi4o1T$$J|!MM0J=AgRvYI zz;;*|XJKqSgBs{njH3I0-vxXRQK$JaYGm(GBaeNYgN7lfU$@q%fp$l&z*y9EJAiyp zd}mO5d<|pZ6VzV6LJctb3D-}0^xyxS1T@2vW<$(Qya%eIxv0I{g0b*7)IiUo271GM zhU(aN(&Z;ab(j`4z{03ARncsM2|0hhZUi(!4~yVr%z?)-Grq-gnC6r_6Rl8Ry49%L zaun0z15}66es_DF4mGiG)Rxu7Lf9MQ;cE2MzzzZ`cnP)V&rmaqaoVjwa@5T8U@#W3 zcw^MHYlGUVzL*JrM(zDp%!>~(52ifh;#JH+XV`xojx{9cFx^Ep_z(l}BWh*hoOPzb z5aPK}9oEG#?1t)i8D_)ZunWFKUAGqJ+^w35`mP+n4S4q)>;EHxsps9^1Yh7IL%bkn z!P8hC-(qPjcG2CAA*hC?pa!%Rb!Ps+x)|*ee~e%w48}F6vvd-*Mfb2ee)b4dBv9?L z`;bgUo!Y|~6Hj6Synu=E9%`lDS^6i`O2xb4J~XK@Ht`Io70Q9SwiQtW?1Tw%8fpUG zast}hqZo!~Pz7WB;r{VCA66#b*j$3Si9be_Pj%IOz-pn=e?$#&pu`2OFsPDlM)DlO%=KdmTfT}keb-I7SWVjV| z?M|TDyNN;g0+Z9fFXnZ()ag;zC=^wo0!GEA$d}6361B8#Fc)^k=r{*8vqk0_)UDc% zaq%K*i*BRZd5+=u3ghek=f2@iZ*kPpx3c&I)ZyBI`SAj3iDTY$hpG_jkTx`jp|0I> z48=dNI0oEusJWd6K{oDfg_j^&!Nh{!L*qAF6*y^qIX?FOLHh{26IsZia_n@b=0AHgqqnG%P)S< zty}|4P5N+D{rRXfbr`i}H&7kNyYD8F{l4b{4M|XeQK&D~X4EyjgKFS!Oove(xa*Sv z(-6;(I#e}L18t4!crYf%rKq#C8&ly~^9kx2#`OMj4W&Tc?=VzGWmLnB%`RAi_)yfT z-i_LdbEvcN1$FK6KXiw(EUM$m7H@$%gzZoR?TuOqZz2I*n>CiP3$?`OQ8RdGao^uA zJqWeL*)cX&L|w01sDZb$cwbZpEZdO9gxE`urJ5;$|m>!3r2Cx9NVtX(Hp2wK@28-(c|3^R-3O{xQ8e%2l15qmS-sI9DmnrKth*7U`s^zWNMAS*7yYIqDa z;$;804sxN+Mj6!B)U)(Xs6#mvW8gfDj!RJkUWGs4I;?<2p1LpQFf2p-EP5RXBzfjO zK!dO=@dX$M<34vwm<+W-1yKX5hnjI0RL3Jx1N;Hw<9tkrYfuB;gUUaP{*^=j$~|ZO zl@RcPf1`zQusO~~4d5Nd#wagcNAXY%Cc#9Q)#Bl(25X}Bwk;;aE;t;AU>E$1d9d>< z_ZQZjSFC?L5{{7IKlP|RdWf1~l-D$hsZfWhGbX@ssDaHweIJ&fR&qCL02$x7mB^0z zP830X0qbL29AJ*}2x!lK#w0ic)xm1i4E|^F6R3{;88nkeP&T*b1kiuGJgNk4Zo96~juXB|D2nG4)5+ zaDCK(Tc8He5w#+o#iv?)HEM$UFe#qJAo}+`AfOfaWCnh61%u53s0J&dDmFot?~cJZ z95urws1;g+x`szE7hXUueU$%PyNS#Y^xBhAn1Js6d@O`*1F;N_Mm2O4 zHIPfF!}}OD^B1Ty6zhwtmjbmiA($LE3$YQd#o`z}Ai%%XWico5jsaeP|GrKqAw3E6 zQ4Q`zE#)5=imy>4PZK4;KckYU0aiw>Ks}2$L9I{+)PVY;R^}(v#FnF0XcuaL$2W3HcLQ#KYQG2S zObkTY^?V}DNF1NR-^9sVbmc!j~e(*)S-HT zIwPM^*DggIx7T@511W==aC7wk_kZ6JP{HA-j%K4qz81B_zoNF{5URt|s1E-`?d3nH z`tMMuKS5lVo(@$$E2@4$)BsDN&P=tq0iM5NTPrXa)$tfBI0rS;Ur-%wv-p1008XJA zzG*(P{5PnMqsDXf5}=koC930$sD6sZA!f!dm<}gf`bJbghfqIif1(cU6OVxZ_Z;=X_=uWu(m?ke$cP$9C~9fL zQCm_4)nRo@Z;d*nJy3^t3~G<(TK*dIf95f4$Iqa5g@CS8iA1i!?@=S1h8p2=)QYS_ z|Di*5d>%FMzfc2vimLaY#RC(&{Isa_5Y(XzL#<>@WJ^8Y5CU5IF{qhNaT&hls0tfU zGdhOq_y*>}m#6^-CvgMJiW*R9R6CVWXQl~i>D!^UaxkjB8JJl2e+>Z*U?1vw97i3l z2dJ67N6kEDQrA!rYG650pW2G3EvbgVSPRurPt>RUN7SjGj2g%S)YfcMy6*pB0y@R# zlz`V!9X~?N_+QjviXY?}&WRduCDf^|iyBBXOK*d!-wieJq2>hCR?kMQ&^7de2|Od9 zjuIww86l_<7DhEx3AJPmP&4Xc={->OJXC{IQCqMA)$uw@-;J92@0NZaby!~|&Q;0?O<*MI%*;fs#41bQgKF;#Y6WhgR`eaJ zd<-w83#34GkR8=_b|Ggts)r*c2XB`_QD;TVEz zFe7?r2xvsFP}e0&YB!L0sD{&`_A(c0sf(eupcHC_8llRyM9r|f#mAry0zj)tcY5%MrIfEpAn0XN7b8$ zYIh_0|NZ|ie}I2Mh-&aU>QAqys0QPvbu&zdiswe%|1zkpYHI1dQT4`Hd?~8E?Wh$x zYVpe!e~2k`|KD3eqI7PlGN3xhgZdymqNpvZjajiH`v3c%$pkdQwWy`vgW8G+)a^KjTH>3Q{sL9r7wiU<(9D3kw)s){ z;ixn44Q9q#s4eM-I%~s&x&JCKfdq9h8FhM>TKpO|BK{OL!%7+4k4JlR3g#t!KL+D- z48=ql-Tf|#If!>e9olI)7}ue;GFv9kEqU=w?pl3=TB4Sy!_p5`@dwLaidx#87XKa9 z&|UMb89T(4OM}|7{HPTzhjpNc$K2xKC#8MS1WPi8_`%XtTN4gW&@IK4q_t(P#1%SekVn8V_EQF~PqRj>+bZyTV# z11(T9Z-eTvFKXq+V=yj4ZRr8jbvuu$e+@O!d&opR-)jOo?eRk046>jKgrP=U!Qyqz zwy2r)Ms+aC;xjD%3#!9isDU4}{L`p@ZecP3j zMukMU^S}!y{G}7L>=<0Il2Fu*-H{M z!Y`%%!O14IQ`MRKHJQ;OMR$(aq z>Jex{;34V@S1ymc_pQyL7)<(XEQ$ZK^nX#`{-C_B;likRP1FagCu-|{Kn-jPY9(f) zz8}j`1NZ(%K!@chYLEX!E$L&_3jB+z7%QJ!+N7wJ2t}38k7}qas(ejUdo3*93sr77 zYUwAV+FOFu^L*gkqJAS{<#!zgq6Ux}^I;a$7p)QMTJ^>WxE}S} z5njNRpNiU&1*ie7#1#7beT{7>WX7<$lXvQk&(t}U~&4{X(54E%4D#azT&qpss5RQ_7j zZ^=p2S$b{;7INisqRvPavkQ7zNSH_Dp#DLmKdSr;RD=65 z2i`{2i(kYY;)19N)ItrcAFAFQ%#IO7xc|Wfo|2#j5)^d}7DHW^=BWI>mOca3;7-(x zZ=eSB88zdy;jW`%sCY}%0Ec1$TxjX%Q7iW%ocpgog9D4Xg849*cwN*;`=CZX-_j3Q z{0{2S#VGFnAjyE5Q4Q392BHQq3pL>Fr~zNI{7)87?Uk?*qkqKaP}B(LT70K@3AIJ9 zQ8PrA-K!oMrK{XVm zv^xtSsB%?MGwy8Z<5BIcxBTBxEBMUPlaz7g3n2Y@zB&Xn^MR-t&$Ref)SjI~o%R@I z-3$t%mbw`#eJtv5ZbMDrDr%qsgufJS%|b7R! ze`V0WG8jz$5>y8fm>=(>2A-mVJN03xdtMv$2gkRl6&j8@Q;SgT9mDkW?|V)_ACiO> z?eBHe2cjsdqZ(!pRJkdr87)Q)_$cac#kUv(6IXJ#DJAA4UI7bZFVy#CH3s80^z7;9nq zssaB0ymxw4FTnr5--}btjl2n#roa$vk9$!|ovC_&uMAc}{pd_U{n@=2OXF+Q%7oPj z@c(Ce-=Xr4V|@&$>Gr-MHYWZ(mc*+b0qt4JS^@t5-ET0e;&-SmS%%f|Bo@O|wcQLF zpni0ILH(+2L7k1gmVOfT<8uY$<9+iL>bEAKj?4FA5Qt7f67&zm3`Xr$C~7IgQCn5h z(p#fC?1MT(BQ1R@>dUwSb=VG|&eTcN7T-gi{*TBOdcKTx-3W`II;x2JEof@-v8d}g z57p4GsMCJM;;&KHEM7gAp9O=7mqZP)CF)FcL#>pDT7mKC|9}7Y69J8M4rKy&0pvJA_G5E0`74Q65x#MNuEDil_ngG{48hy8n|1=oBw8x1$<5j@sk1 zsMCHOb@*PP{I`*3O>7D33%kzpPoUbnhn{Bofq?clK|?o? z45+;iLoHop^j|xR_d@OENYudRpw7U0R6F}nTXF_f|B=N%q6QMw$hB9X5%*sssYZeZ z(gxLFe^kW@sD|gE8eVJp`z-$)YNhU?4)G(@jGv>n>?3LgV>fpHpb~^iuY+p0Rb%eI z5_*uJy&8sUZ~|(trl9t2G3wBq#4tRI`u4|c;yMmTtypQyjdigCjV-(`E z%(cc`kE?XV2#o_PQ@fv8>FO5{d;unKqtv=l{Ads5K~G(a7~ zrl?!d0ac-grT0TE<#5y?oP-+a3e?^oLapc-)NOczVfYF&W45ktrM;R2^p{9))QC5u zmi{&7!ld81r7eq!_d$IxmY~kg7F37FP-o_%rQbkJ>@})Lz`m%J*@F6l?nkwI z4RyvoVOsk4rS9qWq$q|EZ;9HwQK*88Q1^X5Y76e74qc*NZp8|qX4)Nf27W+wxDs`p z4`WVzh+2W5-mYAB^i-iT0Tt|ky3gZL1KErkz-3f}Z&5Qy(#QRkTL85JKclYc0?dX- zP>1X}s=Z`=T|1>v6KR3^PK@Zw{Z~h;NKiw+qfYZR)ZV{B4Xju{*Fg)^UXMY|WG3pv zwAS*Eptj~IYTz;YyYEA0)XFtReUQeYK1kd9bN_XUcaxwG$63^=eT3@Z9cmBb4RGaB zn7L5{E{{6Abx<8Qwe;SoGcz1@7=J{yv(VDlp!(VFSw;lrAmKD>1wNua7>NhEr7D3s zWbIJjfj+1X2U&ayYCyA46Iy{fLwisiT|rIgzWKrQ5)5+JChjV+R{6s z8XAPUc4JXzVlHZCJ2566LT%AW)NQ$L@xM?j@*cHfQ3v}c#J~R~pn_>o4P`+U%#WH; z2~>rusB-mCGi!l5^@C6|o^J6qsDU3rt>`J#8Tl7Aup~p=uVe`N|NEb21fr7B1$BSB zqdM$`8o*%G%8a-4xu~g?*A|XTH1-0 zF~?kkTH-yZ8U112LJjyY?2V7H2(}#New1dReiiRydrZk8*KP2yF)l!@I!Ej@~w=y|M$b%(ohi-vRm z)xjzfG{a4(j&`EH<-egCx{O+(hp6&zEdM|3N<7|(0AF7mh}rNNX2p~v-2lp>4s8vy z4XWLKBUu9d=!~_D2-M-bjGDK?| z(hs4w@HA>b*N}ER-#r4l90yTc~KvvBB;Yz6Sa43Fc0=dZPilL3av%m zj!l-n4KowphdLwoQ2jI+r(46Z>`tH!2`jNI#vSh(u7MiBFjNO)Py?8R+JYshmDp(U zUr{UhJ8C7aqn7-k`5LtXz8_ru_~^g?sR^iHc2t2v7B7cd%9^O#(Ghjnx?BEO%t3rA zs@{Io7M(<`&<$*Y&rsiiZzj0^7Gxvp`|uh)jWp|z_J;&2-W|0>gHTI43AF{&P%~eH zIupB4D-?k$e**Qvx@GDAp#~g%q8ngZGdpU+g(q_VGZH9Af@abI^WqdM5P|CWH2QA` zYHvSTzVD|1{hx94#lzA#3U!taVH1m3)m_p)aW067y%*UTV~Yf;|Fipb)A+ zRn*8@qGr+))zM_sK$oEg7=b!`$4~?M!{QH7XXQPr-WSx0C7$dKaWd3^(p%gMC7=%T zq8coVTJk!mL(~a1qd^uQhvCF$V;EjQO(4z`YuF4$t!N(904t*g)DTNzXJkb^-zoz7 zYjz9jclsjg8a_jfJpWX;WQ9--6+>;!H<$$*q8c8CTCvHfv$P5Q*ATUJ4^dn6(&C@d z|KI<_n&xJh3e|8{R7YVJFOMO_YomTt`dNITh)# zH{YSC_6DN=zyDc4KwGc_RpA(F>2ISxJTFlVel%mxaOIMtI?jWtU(w=?Q02R$wsfe) zC!!`c*IbRBPWLVXn)yD|Qk_7J_#$cvAEG*Vg=#qZOlK0*l4d~F&t-#_viUb{|`IsFKVNQI8x-MyEyM{wBn0R5-AD@j-4fRG{-w~)K zpMkoDD^M%E4mI=5sEI^a`e~1VW^e&D!aJx_{|r^(6>6r@=C~CJL^TkMO3!KWLS|XB z1_qF?Co}I$HOg}zb=xXwR6O31D17ZG+1N^lafIVo;aTK8qToPGhDlM+aV$eQ7SI1A z*0JZwL;N4gJ)r&>;&XT#k+<9Gsf?aS#0TIw|37~dh(aaKmhU{_jMnHu8Y#m2D`|y! z^?bB}Wx=a7vWj|<&k*aR3ib0^8yiTgXM;0jtj68Ws~3@@>8Ln7goO);dg{zQ0F7Bo_5w=9m?xKr~0a|$<+7w z+rU@K8v4s$g>N(Q!c?eDWxkUBXBq!9h;Uc(-eD0dD>hJe9qDG z^3f=_h}Ry^w}XN?DWvPNhta*Y%y*=<;EjByShzoBw%IK5keQJ5Q7S~IlSuDIup!}x zq(9|-&s&5xKals7x3bmkNx586+5Zs)R#GS*8H4pwxI1Z)&-bLIB&`HaAh9luSH$Ji z`GvPQZ{)L&$#f^bA>~_<_?CEY!g@M6e3wbfZE4Nu-?xbdp76#cW1SUxg~uqAfKK%U zlAoT2KUut>HNYP@z6Y*|Z!O{7mL7v}Ey~}*ExdUtGl#r+Scdpq+PjF}k2HAQ8rV+a zXWqMHJm>v}^!en6lQzrBlpx%VcbN_3AJTgfUPxLS>f9&(H*XWtQd^lPbo?jzdfpMP zNjW`(=-+pZ$T<=-Qh0z>Xh-20g!M(#liDhzrd)RmuOk1Yh1)VyJ!i?Uj{|THZ9KP5 zZ;;lC@@=f#B=X1cW{j@&=UGoAf&#l}Fh7+_k=CBH)z(1`DyAboguGXz6($_{yrN!i zBBd?i4)&x>Eh`hycQQS5G`T8q8aRLf=~249XND z-hlKfl+o`%EaI7YyQmV6{zlYOjIyICH;ud|)b~)ogv&_R4_sFU^N-SZlA))Ljj|Dy z>Jk5zf;Y%p>CdGyg{u-zj0t%4ET_!Z&ov@fc(?Ip;-x8HZ^~BU{hhi|c#BeJFX?)+ z>0b+6C*h(>@-(1e3*wcDx3b1}k)Db4CRm&|7GXUB4ERr+N~2#tQApoS{b{_z$@q@^ zR-_%mwbsuUYvW)P_J1FVYb>F!wN#$Y(^08B?{+HwW)&L{Pr;jj_$AW+z;yT>P^3l)3$NIi0_TWLBqv`V@?OVq2kqN%)Pt{k)M+3L6Z6dHYgRCqH?W z$h<>(O5Ui%i()78##-4BtiW4`a@k2wOP_}*=Rg0kNZ4nsccsxHUyZOB;pybnq>P@= z#5eI4rUCvq@;&4Io>zaYq~R??`ftSbB%;m^8+Z)De~`{U68fG{<~`|CqS60rD}0mD z)#5Enyf}qVTKa4Xp0jWX8$>1SOZpqvk8eKiQ#rgxvCH)O? z|NJ9JSZt*Zn@uVB*k6Eugd(j4Z&Kp=bGtcjG{W#d(thAw;iA4( zl&emetf=Q3%2g!4HOBM^G$64Vk-NP62_L2KW_-yTgRq{Bl;dBJ_@7LaJ4;;(3<98M(un+RIw_z@Md<1svr#cW`+iBBLrd+Li$NxX&R zjN)BF%5G~ZfD+e;f6sfshOvUQ)s)lo7e-(X^7ZIva2VyHQbtc1;&lkmw7Nk!#=@sb zuSGaFPSh7fPaA8dW;5|*HU#0}xCYw;^K;A(74G#gAi z%uKrls8<>b@|GjNsg?E5e?EzQNH}GcekHD_1a{yZ>7u@|8a?G=T7DcF%@f&>m3cy5 zN!|)pM#(RDm-Ala%|jbiQBP~aUOoyYWkh-kU|il1tNf6(hSosu<@(Lw^`w#k*%4F7)%B0v^{BQi2q8x z|5<)B>g^{jHE#jRbtFB4@Ic<)yv4~si(#ZcBfpgXf-Gv4MRFQzOhzpmz_KI*CI@C~zgIPHJKyN>s^u1;49JhwuZD72bzI{X=b zw@P;?cbJau@OGo|lDv8@5nqTcF}sy5LD>St^+czWsiY^Q{0YL5&#zY2D@oxaq}Cvz zIN{M>6?#DU5_xH?v6hrM%DW}9mH*Fc)Yp@j&WiBvbWvX`>Ws5Cy3yu%;?-PPcmLB; z_!)&$l9`5#7rgy>tCOCD!g~6AHL!xDza*ZI^g_Jp38z;fo?Vo$Yh`CzU8SEQT!TUU z?K<`?q|AN&1$mypEegcN-^u*Z3Y;Upgm4PHK*iQHaESq2jM>>z(Gc{g~E zlbF>y{~P<07KHJ6M_Aodq+QTo5Rp%L8b3kgE(X)^Nz15BnJ@~667Nl3I>Jq@;|esE zi?B&ol&7>tF{@N-jJs;_@tjtWpH+g>|zm_uXc|g4^47@DyWcU{U zM_O{i_b@(hHtMt`eY?*8QW7GcsAQBO(gnNIcq!aKJPnmAQm#FnceMeiPEpb$pPi(S zp^l#1q&J}M|43WK+kv+$@h#*hqMg>Rn9qAm;uI48qkx{R_=0yaX{UJg{Etd6c^~rj zc1gapgg;R32oB*5;EjAHQm;PoBsRDq#79#0D(_$l9Y;NbqS){Mb_z73aBYl2W=ASN z|Ej^dqu#b%KwN@feaMv!8^?oXVTyX z3QyxLOMVLm_#^q92^X@?R5T~)St#?`HSGJ0=Xr}z?keSm;#}T0gomS#H)iBIEwYAg zlm3~E;dG$q1`V9Byd_wZ^!nI@&YELF@@G>nu9dH1jwSsJZ(`c2#`~wW5tDk6&s+lK zwg1g6@fMZGTW&{7t4bpoXrQn)FcLRYZawbg-A2Bi5BM#nB ziFjkmOtv!KCL)h4vWr542>)#HfA9)vdfxMnB0k3klIyFPjI}hC8$+4xbo3hI5IW-I*4+=I`k@P)h;81_|TlW8mm??)Txx3ra= z@E6MU#Z}}rCT%5kDic1$8->0u5zo*62Fw41Qo!oF1pA)}tfQ=!S%CCVOM6WCJe_19 z{tc!ko|$lS%5LGEL?;!joj1e}TD_a3kFxe6&!4~85)%7RD46#bQvN00o`LP9LUOAx zfR6TAxD?@O&e-9`Ru)N_RN2gEB;roT(_T_-|65MWu}t2mAnI%pOtt$!cFK%Pg>r+ zlzV3RZ3yd$O&fZmQf?h>9n(Mm=})kaR#2I3^gno7QJ^hv^RVLU6p)CRT@ghQ8xex@(=~V`Rgr z(1Nu3q^a%|{zq-z|52%)m1}Apg%K}Aos3wGvPG@oG*Pz9=yPr8)Zs6KrmlP$wB_8( z#;JGI4h;AqAV&V+ym`Y5&b*x\n" "Language-Team: nuxsmin@syspass.org\n" "Language: en_US\n" @@ -25,12 +25,12 @@ msgstr "" "X-Poedit-SearchPath-1: ../../../../lib\n" "X-Poedit-SearchPath-2: ../../../config\n" -#: ../../../../lib/SP/Bootstrap.php:267 +#: ../../../../lib/SP/Bootstrap.php:278 #, php-format msgid "Versión de PHP requerida >= %s <= %s" msgstr "Required PHP version >= %s <= %s" -#: ../../../../lib/SP/Bootstrap.php:269 +#: ../../../../lib/SP/Bootstrap.php:280 msgid "" "Actualice la versión de PHP para que la aplicación funcione correctamente" msgstr "Please update the PHP version to run sysPass" @@ -53,7 +53,7 @@ msgid "Actual: %s - Necesario: 750" msgstr "Current: %s - Needed: 750" #: ../../../../lib/SP/Core/Acl/AccountPermissionException.php:45 -#: ../../../../lib/SP/Util/ErrorUtil.php:132 +#: ../../../../lib/SP/Util/ErrorUtil.php:142 #: ../../../modules/web/Controllers/Helpers/Account/AccountPasswordHelper.php:96 msgid "No tiene permisos para acceder a esta cuenta" msgstr "You don't have permission to access to this account" @@ -61,12 +61,12 @@ msgstr "You don't have permission to access to this account" #: ../../../../lib/SP/Core/Acl/AccountPermissionException.php:45 #: ../../../../lib/SP/Core/Acl/UnauthorizedActionException.php:46 #: ../../../../lib/SP/Core/Acl/UnauthorizedPageException.php:45 -#: ../../../../lib/SP/Util/ErrorUtil.php:129 -#: ../../../../lib/SP/Util/ErrorUtil.php:133 -#: ../../../../lib/SP/Util/ErrorUtil.php:137 -#: ../../../../lib/SP/Util/ErrorUtil.php:141 -#: ../../../../lib/SP/Util/ErrorUtil.php:149 -#: ../../../../lib/SP/Util/ErrorUtil.php:156 +#: ../../../../lib/SP/Util/ErrorUtil.php:139 +#: ../../../../lib/SP/Util/ErrorUtil.php:143 +#: ../../../../lib/SP/Util/ErrorUtil.php:147 +#: ../../../../lib/SP/Util/ErrorUtil.php:151 +#: ../../../../lib/SP/Util/ErrorUtil.php:159 +#: ../../../../lib/SP/Util/ErrorUtil.php:166 #: ../../../modules/web/Controllers/ErrorController.php:124 #: ../../../modules/web/Controllers/UserPassResetController.php:94 #: ../../../modules/web/themes/material-blue/views/upgrade/index.inc:13 @@ -75,7 +75,7 @@ msgstr "Please contact to the administrator" # Not available #: ../../../../lib/SP/Core/Acl/Acl.php:294 -#: ../../../../lib/SP/Services/Auth/LoginService.php:600 +#: ../../../../lib/SP/Services/Auth/LoginService.php:604 msgid "N/D" msgstr "N/A" @@ -96,24 +96,24 @@ msgstr "Action" #: ../../../../lib/SP/Providers/Auth/Ldap/LdapMsAds.php:155 #: ../../../../lib/SP/Providers/Auth/Ldap/LdapStd.php:110 #: ../../../../lib/SP/Providers/Auth/Ldap/LdapStd.php:142 -#: ../../../../lib/SP/Services/Auth/LoginService.php:217 -#: ../../../../lib/SP/Services/Auth/LoginService.php:235 -#: ../../../../lib/SP/Services/Auth/LoginService.php:386 -#: ../../../../lib/SP/Services/Auth/LoginService.php:453 -#: ../../../../lib/SP/Services/Auth/LoginService.php:561 -#: ../../../../lib/SP/Services/Auth/LoginService.php:604 +#: ../../../../lib/SP/Services/Auth/LoginService.php:220 +#: ../../../../lib/SP/Services/Auth/LoginService.php:238 +#: ../../../../lib/SP/Services/Auth/LoginService.php:390 +#: ../../../../lib/SP/Services/Auth/LoginService.php:457 +#: ../../../../lib/SP/Services/Auth/LoginService.php:565 +#: ../../../../lib/SP/Services/Auth/LoginService.php:608 #: ../../../../lib/SP/Services/Ldap/LdapImportService.php:238 #: ../../../modules/web/Controllers/Helpers/Account/AccountSearchHelper.php:253 #: ../../../modules/web/Controllers/Helpers/Grid/AuthTokenGrid.php:106 #: ../../../modules/web/Controllers/Helpers/Grid/ItemPresetGrid.php:107 #: ../../../modules/web/Controllers/Helpers/Grid/PublicLinkGrid.php:111 #: ../../../modules/web/Controllers/Helpers/Grid/TrackGrid.php:105 -#: ../../../modules/web/Controllers/LoginController.php:102 +#: ../../../modules/web/Controllers/LoginController.php:120 #: ../../../modules/web/Controllers/UserController.php:278 #: ../../../modules/web/Controllers/UserController.php:312 #: ../../../modules/web/Controllers/UserController.php:373 #: ../../../modules/web/Controllers/UserController.php:412 -#: ../../../modules/web/Controllers/UserPassResetController.php:187 +#: ../../../modules/web/Controllers/UserPassResetController.php:190 #: ../../../modules/web/themes/material-blue/views/account/account-editpass.inc:55 #: ../../../modules/web/themes/material-blue/views/account/account-editpass.inc:61 #: ../../../modules/web/themes/material-blue/views/account/account-history.inc:91 @@ -151,7 +151,7 @@ msgid "Acción no encontrada" msgstr "Action not found" #: ../../../../lib/SP/Core/Acl/UnauthorizedActionException.php:46 -#: ../../../../lib/SP/Util/ErrorUtil.php:140 +#: ../../../../lib/SP/Util/ErrorUtil.php:150 #: ../../../modules/web/Controllers/AccountFileController.php:261 #: ../../../modules/web/Controllers/AccountHistoryManagerController.php:59 #: ../../../modules/web/Controllers/AccountManagerController.php:77 @@ -200,8 +200,8 @@ msgstr "Action not found" #: ../../../modules/web/Controllers/NotificationController.php:288 #: ../../../modules/web/Controllers/NotificationController.php:315 #: ../../../modules/web/Controllers/NotificationController.php:348 -#: ../../../modules/web/Controllers/PluginController.php:98 -#: ../../../modules/web/Controllers/PluginController.php:117 +#: ../../../modules/web/Controllers/PluginController.php:103 +#: ../../../modules/web/Controllers/PluginController.php:122 #: ../../../modules/web/Controllers/PublicLinkController.php:71 #: ../../../modules/web/Controllers/PublicLinkController.php:105 #: ../../../modules/web/Controllers/PublicLinkController.php:167 @@ -244,7 +244,7 @@ msgid "No tiene permisos para realizar esta operación" msgstr "You don't have permission to do this operation" #: ../../../../lib/SP/Core/Acl/UnauthorizedPageException.php:45 -#: ../../../../lib/SP/Util/ErrorUtil.php:136 +#: ../../../../lib/SP/Util/ErrorUtil.php:146 msgid "No tiene permisos para acceder a esta página" msgstr "You don't have permission to access this page" @@ -280,14 +280,14 @@ msgstr "Session cannot be initialized" #: ../../../../lib/SP/Services/Account/AccountService.php:227 #: ../../../../lib/SP/Services/Account/AccountService.php:232 #: ../../../../lib/SP/Services/Api/ApiService.php:129 -#: ../../../../lib/SP/Services/Api/ApiService.php:227 -#: ../../../../lib/SP/Services/Api/ApiService.php:235 -#: ../../../../lib/SP/Services/Auth/LoginService.php:187 -#: ../../../../lib/SP/Services/Auth/LoginService.php:351 -#: ../../../../lib/SP/Services/Auth/LoginService.php:500 -#: ../../../../lib/SP/Services/Auth/LoginService.php:505 -#: ../../../../lib/SP/Services/Auth/LoginService.php:537 -#: ../../../../lib/SP/Services/Auth/LoginService.php:644 +#: ../../../../lib/SP/Services/Api/ApiService.php:229 +#: ../../../../lib/SP/Services/Api/ApiService.php:237 +#: ../../../../lib/SP/Services/Auth/LoginService.php:190 +#: ../../../../lib/SP/Services/Auth/LoginService.php:354 +#: ../../../../lib/SP/Services/Auth/LoginService.php:504 +#: ../../../../lib/SP/Services/Auth/LoginService.php:509 +#: ../../../../lib/SP/Services/Auth/LoginService.php:541 +#: ../../../../lib/SP/Services/Auth/LoginService.php:648 #: ../../../../lib/SP/Services/AuthToken/AuthTokenService.php:311 #: ../../../../lib/SP/Services/CustomField/CustomFieldService.php:203 #: ../../../../lib/SP/Services/Export/XmlVerifyService.php:108 @@ -306,7 +306,7 @@ msgstr "Crypto module cannot be loaded" msgid "Error al generar datos cifrados" msgstr "Error while creating the encrypted data" -#: ../../../../lib/SP/Core/Events/Event.php:56 +#: ../../../../lib/SP/Core/Events/Event.php:57 msgid "Es necesario un objeto" msgstr "An object is needed" @@ -320,17 +320,17 @@ msgstr "Invalid icons class" #: ../../../../lib/SP/DataModel/PublicLinkListData.php:88 #: ../../../../lib/SP/Providers/Auth/Ldap/LdapConnection.php:190 -#: ../../../modules/web/Controllers/AccountController.php:227 +#: ../../../modules/web/Controllers/AccountController.php:226 msgid "ON" msgstr "ON" #: ../../../../lib/SP/DataModel/PublicLinkListData.php:88 -#: ../../../modules/web/Controllers/AccountController.php:227 +#: ../../../modules/web/Controllers/AccountController.php:226 msgid "OFF" msgstr "OFF" #: ../../../../lib/SP/Html/DataGrid/DataGridBase.php:303 -#: ../../../../lib/SP/Mvc/View/Template.php:122 +#: ../../../../lib/SP/Mvc/View/Template.php:126 #, php-format msgid "No es posible obtener la plantilla \"%s\" : %s" msgstr "Unable to retrieve the \"%s\" template: %s" @@ -352,11 +352,11 @@ msgstr "Encoding error" msgid "Respuesta XML-RPC inválida" msgstr "Invalid XML-RPC response" -#: ../../../../lib/SP/Mvc/Controller/ControllerTrait.php:64 +#: ../../../../lib/SP/Mvc/Controller/ControllerTrait.php:71 msgid "La sesión no se ha iniciado o ha caducado" msgstr "Session not started or timed out" -#: ../../../../lib/SP/Mvc/Controller/ControllerTrait.php:114 +#: ../../../../lib/SP/Mvc/Controller/ControllerTrait.php:124 msgid "Acción Inválida" msgstr "Invalid Action" @@ -398,41 +398,69 @@ msgstr "Invalid filter type" msgid "Tipo de objeto incorrecto" msgstr "Wrong object type" -#: ../../../../lib/SP/Mvc/View/Template.php:274 -#: ../../../../lib/SP/Mvc/View/Template.php:276 +#: ../../../../lib/SP/Mvc/View/Template.php:278 +#: ../../../../lib/SP/Mvc/View/Template.php:280 #, php-format msgid "No es posible obtener la variable \"%s\"" msgstr "Unable to retrieve the \"%s\" variable" -#: ../../../../lib/SP/Mvc/View/Template.php:322 -#: ../../../../lib/SP/Mvc/View/Template.php:324 +#: ../../../../lib/SP/Mvc/View/Template.php:326 +#: ../../../../lib/SP/Mvc/View/Template.php:328 #, php-format msgid "No es posible destruir la variable \"%s\"" msgstr "Unable to unset the \"%s\" variable" -#: ../../../../lib/SP/Mvc/View/Template.php:341 +#: ../../../../lib/SP/Mvc/View/Template.php:345 msgid "La plantilla no contiene archivos" msgstr "Template does not contain files" -#: ../../../../lib/SP/Plugin/PluginManager.php:113 -#: ../../../../lib/SP/Plugin/PluginManager.php:256 +#: ../../../../lib/SP/Plugin/PluginManager.php:170 +#, php-format +msgid "Versión de plugin no compatible (%s)" +msgstr "Plugin version not compatible (%s)" + +#: ../../../../lib/SP/Plugin/PluginManager.php:192 #, php-format msgid "No es posible cargar el plugin \"%s\"" msgstr "Unable to load the \"%s\" plugin" +#: ../../../../lib/SP/Plugin/PluginManager.php:194 +#: ../../../modules/web/Controllers/Helpers/Grid/PluginGrid.php:101 +msgid "Plugin" +msgstr "Plugin" + +#: ../../../../lib/SP/Plugin/PluginManager.php:219 +#: ../../../../lib/SP/Plugin/PluginManager.php:339 +#: ../../../modules/web/Controllers/PluginController.php:213 +#: ../../../modules/web/Controllers/PluginController.php:216 +msgid "Plugin deshabilitado" +msgstr "Plugin disabled" + +#: ../../../../lib/SP/Plugin/PluginManager.php:254 +msgid "Plugin disponible" +msgstr "Plugin available" + +#: ../../../../lib/SP/Plugin/PluginManager.php:264 +msgid "Plugin no disponible" +msgstr "Plugin unavailable" + +#: ../../../../lib/SP/Plugin/PluginManager.php:294 +msgid "Plugin cargado" +msgstr "Plugin loaded" + #. (itstool) path: action/text -#: ../../../../lib/SP/Plugin/PluginManager.php:245 +#: ../../../../lib/SP/Plugin/PluginManager.php:319 #: ../../../config/actions.xml:535 msgid "Nuevo Plugin" msgstr "New Plugin" -#: ../../../../lib/SP/Plugin/PluginManager.php:246 +#: ../../../../lib/SP/Plugin/PluginManager.php:320 #: ../../../modules/api/Controllers/AccountController.php:71 #: ../../../modules/api/Controllers/AccountController.php:103 #: ../../../modules/api/Controllers/AccountController.php:139 -#: ../../../modules/api/Controllers/AccountController.php:185 -#: ../../../modules/api/Controllers/AccountController.php:235 -#: ../../../modules/api/Controllers/AccountController.php:310 +#: ../../../modules/api/Controllers/AccountController.php:189 +#: ../../../modules/api/Controllers/AccountController.php:240 +#: ../../../modules/api/Controllers/AccountController.php:315 #: ../../../modules/api/Controllers/CategoryController.php:63 #: ../../../modules/api/Controllers/CategoryController.php:92 #: ../../../modules/api/Controllers/CategoryController.php:122 @@ -490,7 +518,7 @@ msgid "Método ya inicializado" msgstr "Method already initialized" #: ../../../../lib/SP/Providers/Auth/Ldap/LdapActions.php:119 -#: ../../../../lib/SP/Providers/Auth/Ldap/LdapActions.php:125 +#: ../../../../lib/SP/Providers/Auth/Ldap/LdapActions.php:126 msgid "Error al buscar RDN de grupo" msgstr "Error while searching the group RDN" @@ -518,13 +546,13 @@ msgstr "Error while searching the group RDN" msgid "Grupo" msgstr "Group" -#: ../../../../lib/SP/Providers/Auth/Ldap/LdapActions.php:200 -#: ../../../../lib/SP/Providers/Auth/Ldap/LdapActions.php:204 +#: ../../../../lib/SP/Providers/Auth/Ldap/LdapActions.php:205 +#: ../../../../lib/SP/Providers/Auth/Ldap/LdapActions.php:210 msgid "Error al localizar el usuario en LDAP" msgstr "Error while searching the user on LDAP" -#: ../../../../lib/SP/Providers/Auth/Ldap/LdapActions.php:249 -#: ../../../../lib/SP/Providers/Auth/Ldap/LdapActions.php:254 +#: ../../../../lib/SP/Providers/Auth/Ldap/LdapActions.php:259 +#: ../../../../lib/SP/Providers/Auth/Ldap/LdapActions.php:265 msgid "Error al buscar objetos en DN base" msgstr "Error while searching objects in base DN" @@ -594,7 +622,7 @@ msgid "No es posible inicializar" msgstr "Unable to initialize" #: ../../../../lib/SP/Providers/Notification/NotificationHandler.php:124 -#: ../../../modules/web/Controllers/AccountController.php:926 +#: ../../../modules/web/Controllers/AccountController.php:925 msgid "Solicitud" msgstr "Request" @@ -1121,7 +1149,7 @@ msgstr "The account doesn't exist" #: ../../../../lib/SP/Services/Api/ApiRequest.php:79 #: ../../../../lib/SP/Services/Api/ApiRequest.php:113 -#: ../../../../lib/SP/Services/Api/ApiService.php:229 +#: ../../../../lib/SP/Services/Api/ApiService.php:231 msgid "Datos inválidos" msgstr "Invalid data" @@ -1130,7 +1158,7 @@ msgid "Fomato incorrecto" msgstr "Invalid format" #: ../../../../lib/SP/Services/Api/ApiService.php:96 -#: ../../../../lib/SP/Services/Auth/LoginService.php:137 +#: ../../../../lib/SP/Services/Auth/LoginService.php:138 #: ../../../../lib/SP/Services/UserPassRecover/UserPassRecoverService.php:103 #: ../../../modules/web/Controllers/UserPassResetController.php:124 msgid "Intentos excedidos" @@ -1145,54 +1173,54 @@ msgstr "Wrong parameters" msgid "Acceso no permitido" msgstr "Unauthorized access" -#: ../../../../lib/SP/Services/Auth/LoginService.php:157 -#: ../../../../lib/SP/Services/Auth/LoginService.php:456 -#: ../../../../lib/SP/Services/Auth/LoginService.php:463 -#: ../../../../lib/SP/Services/Auth/LoginService.php:571 -#: ../../../../lib/SP/Services/Auth/LoginService.php:576 -#: ../../../../lib/SP/Services/Auth/LoginService.php:615 -#: ../../../../lib/SP/Services/Auth/LoginService.php:620 +#: ../../../../lib/SP/Services/Auth/LoginService.php:160 +#: ../../../../lib/SP/Services/Auth/LoginService.php:460 +#: ../../../../lib/SP/Services/Auth/LoginService.php:467 +#: ../../../../lib/SP/Services/Auth/LoginService.php:575 +#: ../../../../lib/SP/Services/Auth/LoginService.php:580 +#: ../../../../lib/SP/Services/Auth/LoginService.php:619 +#: ../../../../lib/SP/Services/Auth/LoginService.php:624 msgid "Login incorrecto" msgstr "Wrong login" -#: ../../../../lib/SP/Services/Auth/LoginService.php:216 -#: ../../../../lib/SP/Services/Auth/LoginService.php:223 +#: ../../../../lib/SP/Services/Auth/LoginService.php:219 +#: ../../../../lib/SP/Services/Auth/LoginService.php:226 msgid "Usuario deshabilitado" msgstr "User disabled" -#: ../../../../lib/SP/Services/Auth/LoginService.php:270 +#: ../../../../lib/SP/Services/Auth/LoginService.php:273 msgid "Usando clave temporal" msgstr "Using temporary password" -#: ../../../../lib/SP/Services/Auth/LoginService.php:282 -#: ../../../../lib/SP/Services/Auth/LoginService.php:288 -#: ../../../../lib/SP/Services/Auth/LoginService.php:306 -#: ../../../../lib/SP/Services/Auth/LoginService.php:312 +#: ../../../../lib/SP/Services/Auth/LoginService.php:285 +#: ../../../../lib/SP/Services/Auth/LoginService.php:291 +#: ../../../../lib/SP/Services/Auth/LoginService.php:309 +#: ../../../../lib/SP/Services/Auth/LoginService.php:315 msgid "Clave maestra incorrecta" msgstr "Wrong master password" -#: ../../../../lib/SP/Services/Auth/LoginService.php:297 -#: ../../../../lib/SP/Services/Auth/LoginService.php:321 +#: ../../../../lib/SP/Services/Auth/LoginService.php:300 +#: ../../../../lib/SP/Services/Auth/LoginService.php:324 #: ../../../../lib/SP/Services/User/UpdatedMasterPassException.php:45 -#: ../../../../lib/SP/Util/ErrorUtil.php:144 +#: ../../../../lib/SP/Util/ErrorUtil.php:154 #: ../../../modules/web/Controllers/ConfigEncryptionController.php:68 #: ../../../modules/web/Controllers/ConfigEncryptionController.php:142 #: ../../../modules/web/Controllers/Helpers/Account/AccountPasswordHelper.php:116 msgid "Clave maestra actualizada" msgstr "Master password updated" -#: ../../../../lib/SP/Services/Auth/LoginService.php:327 +#: ../../../../lib/SP/Services/Auth/LoginService.php:330 msgid "Es necesaria su clave anterior" msgstr "Your previous password is needed" -#: ../../../../lib/SP/Services/Auth/LoginService.php:339 +#: ../../../../lib/SP/Services/Auth/LoginService.php:342 msgid "La clave maestra no ha sido guardada o es incorrecta" msgstr "The Master Password either is not saved or is wrong" -#: ../../../../lib/SP/Services/Auth/LoginService.php:451 -#: ../../../../lib/SP/Services/Auth/LoginService.php:514 -#: ../../../../lib/SP/Services/Auth/LoginService.php:560 -#: ../../../../lib/SP/Services/Auth/LoginService.php:603 +#: ../../../../lib/SP/Services/Auth/LoginService.php:455 +#: ../../../../lib/SP/Services/Auth/LoginService.php:518 +#: ../../../../lib/SP/Services/Auth/LoginService.php:564 +#: ../../../../lib/SP/Services/Auth/LoginService.php:607 #: ../../../modules/web/Controllers/AccountFileController.php:235 #: ../../../modules/web/Controllers/Helpers/Grid/CustomFieldGrid.php:108 #: ../../../modules/web/Controllers/Helpers/Grid/FileGrid.php:108 @@ -1207,22 +1235,22 @@ msgstr "The Master Password either is not saved or is wrong" msgid "Tipo" msgstr "Type" -#: ../../../../lib/SP/Services/Auth/LoginService.php:452 -#: ../../../../lib/SP/Services/Auth/LoginService.php:515 +#: ../../../../lib/SP/Services/Auth/LoginService.php:456 +#: ../../../../lib/SP/Services/Auth/LoginService.php:519 msgid "Servidor LDAP" msgstr "LDAP Server" -#: ../../../../lib/SP/Services/Auth/LoginService.php:471 -#: ../../../../lib/SP/Services/Auth/LoginService.php:476 +#: ../../../../lib/SP/Services/Auth/LoginService.php:475 +#: ../../../../lib/SP/Services/Auth/LoginService.php:480 msgid "Cuenta expirada" msgstr "Account expired" -#: ../../../../lib/SP/Services/Auth/LoginService.php:484 -#: ../../../../lib/SP/Services/Auth/LoginService.php:489 +#: ../../../../lib/SP/Services/Auth/LoginService.php:488 +#: ../../../../lib/SP/Services/Auth/LoginService.php:493 msgid "El usuario no tiene grupos asociados" msgstr "The user has no associated groups" -#: ../../../../lib/SP/Services/Auth/LoginService.php:605 +#: ../../../../lib/SP/Services/Auth/LoginService.php:609 #: ../../../modules/web/themes/material-blue/views/config/general-auth.inc:10 msgid "Autentificación" msgstr "Authentication" @@ -1503,16 +1531,16 @@ msgstr "Account imported" #: ../../../modules/api/Controllers/AccountController.php:72 #: ../../../modules/api/Controllers/AccountController.php:104 #: ../../../modules/api/Controllers/AccountController.php:140 -#: ../../../modules/api/Controllers/AccountController.php:186 -#: ../../../modules/api/Controllers/AccountController.php:236 -#: ../../../modules/api/Controllers/AccountController.php:311 -#: ../../../modules/web/Controllers/AccountController.php:225 -#: ../../../modules/web/Controllers/AccountController.php:720 -#: ../../../modules/web/Controllers/AccountController.php:765 -#: ../../../modules/web/Controllers/AccountController.php:806 -#: ../../../modules/web/Controllers/AccountController.php:845 -#: ../../../modules/web/Controllers/AccountController.php:895 -#: ../../../modules/web/Controllers/AccountController.php:929 +#: ../../../modules/api/Controllers/AccountController.php:190 +#: ../../../modules/api/Controllers/AccountController.php:241 +#: ../../../modules/api/Controllers/AccountController.php:316 +#: ../../../modules/web/Controllers/AccountController.php:224 +#: ../../../modules/web/Controllers/AccountController.php:719 +#: ../../../modules/web/Controllers/AccountController.php:764 +#: ../../../modules/web/Controllers/AccountController.php:805 +#: ../../../modules/web/Controllers/AccountController.php:844 +#: ../../../modules/web/Controllers/AccountController.php:894 +#: ../../../modules/web/Controllers/AccountController.php:928 #: ../../../modules/web/Controllers/AccountFileController.php:234 #: ../../../modules/web/Controllers/AccountHistoryManagerController.php:112 #: ../../../modules/web/Controllers/AccountHistoryManagerController.php:147 @@ -2119,7 +2147,7 @@ msgid "Enlace" msgstr "Link" #: ../../../../lib/SP/Services/User/UpdatedMasterPassException.php:45 -#: ../../../../lib/SP/Util/ErrorUtil.php:145 +#: ../../../../lib/SP/Util/ErrorUtil.php:155 #: ../../../modules/web/Controllers/ConfigEncryptionController.php:68 #: ../../../modules/web/Controllers/ConfigEncryptionController.php:142 #: ../../../modules/web/Controllers/Helpers/Account/AccountPasswordHelper.php:116 @@ -2286,12 +2314,12 @@ msgstr "Socket not initialized" msgid "Error al enviar datos" msgstr "Error while sending the data" -#: ../../../../lib/SP/Util/ErrorUtil.php:128 +#: ../../../../lib/SP/Util/ErrorUtil.php:138 msgid "Opción no disponible" msgstr "Option unavailable" -#: ../../../../lib/SP/Util/ErrorUtil.php:148 -#: ../../../../lib/SP/Util/ErrorUtil.php:155 +#: ../../../../lib/SP/Util/ErrorUtil.php:158 +#: ../../../../lib/SP/Util/ErrorUtil.php:165 msgid "Se ha producido una excepción" msgstr "An exception occured" @@ -2304,40 +2332,40 @@ msgid "Cuenta visualizada" msgstr "Account displayed" #: ../../../modules/api/Controllers/AccountController.php:102 -#: ../../../modules/web/Controllers/AccountController.php:554 -#: ../../../modules/web/Controllers/AccountController.php:610 +#: ../../../modules/web/Controllers/AccountController.php:553 +#: ../../../modules/web/Controllers/AccountController.php:609 msgid "Clave visualizada" msgstr "Password viewed" #: ../../../modules/api/Controllers/AccountController.php:138 #: ../../../modules/api/Controllers/AccountController.php:144 -#: ../../../modules/web/Controllers/AccountController.php:804 -#: ../../../modules/web/Controllers/AccountController.php:815 +#: ../../../modules/web/Controllers/AccountController.php:803 +#: ../../../modules/web/Controllers/AccountController.php:814 #: ../../../modules/web/Controllers/UserController.php:411 #: ../../../modules/web/Controllers/UserController.php:415 -#: ../../../modules/web/Controllers/UserPassResetController.php:186 -#: ../../../modules/web/Controllers/UserPassResetController.php:190 +#: ../../../modules/web/Controllers/UserPassResetController.php:189 +#: ../../../modules/web/Controllers/UserPassResetController.php:193 msgid "Clave actualizada" msgstr "Password updated" -#: ../../../modules/api/Controllers/AccountController.php:184 -#: ../../../modules/api/Controllers/AccountController.php:190 -#: ../../../modules/web/Controllers/AccountController.php:718 -#: ../../../modules/web/Controllers/AccountController.php:729 +#: ../../../modules/api/Controllers/AccountController.php:188 +#: ../../../modules/api/Controllers/AccountController.php:194 +#: ../../../modules/web/Controllers/AccountController.php:717 +#: ../../../modules/web/Controllers/AccountController.php:728 msgid "Cuenta creada" msgstr "Account added" -#: ../../../modules/api/Controllers/AccountController.php:234 -#: ../../../modules/api/Controllers/AccountController.php:240 -#: ../../../modules/web/Controllers/AccountController.php:763 -#: ../../../modules/web/Controllers/AccountController.php:774 +#: ../../../modules/api/Controllers/AccountController.php:239 +#: ../../../modules/api/Controllers/AccountController.php:245 +#: ../../../modules/web/Controllers/AccountController.php:762 +#: ../../../modules/web/Controllers/AccountController.php:773 msgid "Cuenta actualizada" msgstr "Account updated" -#: ../../../modules/api/Controllers/AccountController.php:309 -#: ../../../modules/api/Controllers/AccountController.php:315 -#: ../../../modules/web/Controllers/AccountController.php:893 -#: ../../../modules/web/Controllers/AccountController.php:898 +#: ../../../modules/api/Controllers/AccountController.php:314 +#: ../../../modules/api/Controllers/AccountController.php:320 +#: ../../../modules/web/Controllers/AccountController.php:892 +#: ../../../modules/web/Controllers/AccountController.php:897 #: ../../../modules/web/Controllers/AccountHistoryManagerController.php:110 #: ../../../modules/web/Controllers/AccountHistoryManagerController.php:115 #: ../../../modules/web/Controllers/AccountManagerController.php:145 @@ -2709,9 +2737,9 @@ msgstr "Group deleted" msgid "Es necesario actualizar" msgstr "Updating needed" -#: ../../../modules/web/Controllers/AccountController.php:149 -#: ../../../modules/web/Controllers/AccountController.php:204 -#: ../../../modules/web/Controllers/AccountController.php:474 +#: ../../../modules/web/Controllers/AccountController.php:148 +#: ../../../modules/web/Controllers/AccountController.php:203 +#: ../../../modules/web/Controllers/AccountController.php:473 #: ../../../modules/web/Controllers/Helpers/Account/AccountActionsHelper.php:60 #: ../../../modules/web/Controllers/Helpers/Account/AccountActionsHelper.php:61 #: ../../../modules/web/Controllers/Helpers/Grid/AccountGrid.php:159 @@ -2721,21 +2749,21 @@ msgstr "Updating needed" msgid "Detalles de Cuenta" msgstr "Account Details" -#: ../../../modules/web/Controllers/AccountController.php:223 +#: ../../../modules/web/Controllers/AccountController.php:222 msgid "Enlace visualizado" msgstr "Link viewed" -#: ../../../modules/web/Controllers/AccountController.php:224 -#: ../../../modules/web/Controllers/AccountController.php:555 -#: ../../../modules/web/Controllers/AccountController.php:611 -#: ../../../modules/web/Controllers/AccountController.php:650 -#: ../../../modules/web/Controllers/AccountController.php:684 -#: ../../../modules/web/Controllers/AccountController.php:719 -#: ../../../modules/web/Controllers/AccountController.php:764 -#: ../../../modules/web/Controllers/AccountController.php:805 -#: ../../../modules/web/Controllers/AccountController.php:844 -#: ../../../modules/web/Controllers/AccountController.php:894 -#: ../../../modules/web/Controllers/AccountController.php:928 +#: ../../../modules/web/Controllers/AccountController.php:223 +#: ../../../modules/web/Controllers/AccountController.php:554 +#: ../../../modules/web/Controllers/AccountController.php:610 +#: ../../../modules/web/Controllers/AccountController.php:649 +#: ../../../modules/web/Controllers/AccountController.php:683 +#: ../../../modules/web/Controllers/AccountController.php:718 +#: ../../../modules/web/Controllers/AccountController.php:763 +#: ../../../modules/web/Controllers/AccountController.php:804 +#: ../../../modules/web/Controllers/AccountController.php:843 +#: ../../../modules/web/Controllers/AccountController.php:893 +#: ../../../modules/web/Controllers/AccountController.php:927 #: ../../../modules/web/Controllers/AccountFileController.php:233 #: ../../../modules/web/Controllers/AccountHistoryManagerController.php:111 #: ../../../modules/web/Controllers/AccountHistoryManagerController.php:146 @@ -2749,24 +2777,24 @@ msgstr "Link viewed" msgid "Cuenta" msgstr "Account" -#: ../../../modules/web/Controllers/AccountController.php:226 +#: ../../../modules/web/Controllers/AccountController.php:225 msgid "Agente" msgstr "Agent" -#: ../../../modules/web/Controllers/AccountController.php:227 +#: ../../../modules/web/Controllers/AccountController.php:226 msgid "HTTPS" msgstr "HTTPS" #. (itstool) path: action/text -#: ../../../modules/web/Controllers/AccountController.php:256 -#: ../../../modules/web/Controllers/AccountController.php:300 -#: ../../../modules/web/Controllers/Helpers/LayoutHelper.php:278 +#: ../../../modules/web/Controllers/AccountController.php:255 +#: ../../../modules/web/Controllers/AccountController.php:299 +#: ../../../modules/web/Controllers/Helpers/LayoutHelper.php:280 #: ../../../config/actions.xml:157 msgid "Nueva Cuenta" msgstr "New Account" #. (itstool) path: action/text -#: ../../../modules/web/Controllers/AccountController.php:344 +#: ../../../modules/web/Controllers/AccountController.php:343 #: ../../../modules/web/Controllers/Helpers/Account/AccountActionsHelper.php:176 #: ../../../modules/web/Controllers/Helpers/Account/AccountActionsHelper.php:177 #: ../../../modules/web/themes/material-blue/views/account/linkedAccounts.inc:18 @@ -2775,7 +2803,7 @@ msgid "Editar Cuenta" msgstr "Edit Account" #. (itstool) path: action/text -#: ../../../modules/web/Controllers/AccountController.php:389 +#: ../../../modules/web/Controllers/AccountController.php:388 #: ../../../modules/web/Controllers/Helpers/Account/AccountActionsHelper.php:334 #: ../../../modules/web/Controllers/Helpers/Account/AccountActionsHelper.php:335 #: ../../../modules/web/Controllers/Helpers/Grid/AccountGrid.php:176 @@ -2787,26 +2815,26 @@ msgstr "Edit Account" msgid "Eliminar Cuenta" msgstr "Remove Account" -#: ../../../modules/web/Controllers/AccountController.php:432 +#: ../../../modules/web/Controllers/AccountController.php:431 #: ../../../modules/web/Controllers/Helpers/Account/AccountActionsHelper.php:155 #: ../../../modules/web/Controllers/Helpers/Account/AccountActionsHelper.php:156 msgid "Modificar Clave de Cuenta" msgstr "Edit Account Password" -#: ../../../modules/web/Controllers/AccountController.php:649 -#: ../../../modules/web/Controllers/AccountController.php:683 +#: ../../../modules/web/Controllers/AccountController.php:648 +#: ../../../modules/web/Controllers/AccountController.php:682 msgid "Clave copiada" msgstr "Password copied" -#: ../../../modules/web/Controllers/AccountController.php:843 -#: ../../../modules/web/Controllers/AccountController.php:854 +#: ../../../modules/web/Controllers/AccountController.php:842 +#: ../../../modules/web/Controllers/AccountController.php:853 #: ../../../modules/web/Controllers/AccountHistoryManagerController.php:145 #: ../../../modules/web/Controllers/AccountHistoryManagerController.php:150 msgid "Cuenta restaurada" msgstr "Account restored" -#: ../../../modules/web/Controllers/AccountController.php:879 -#: ../../../modules/web/Controllers/AccountController.php:882 +#: ../../../modules/web/Controllers/AccountController.php:878 +#: ../../../modules/web/Controllers/AccountController.php:881 #: ../../../modules/web/Controllers/AccountHistoryManagerController.php:99 #: ../../../modules/web/Controllers/AccountHistoryManagerController.php:102 #: ../../../modules/web/Controllers/AccountManagerController.php:131 @@ -2814,16 +2842,16 @@ msgstr "Account restored" msgid "Cuentas eliminadas" msgstr "Accounts removed" -#: ../../../modules/web/Controllers/AccountController.php:919 +#: ../../../modules/web/Controllers/AccountController.php:918 #: ../../../modules/web/Forms/NotificationForm.php:100 msgid "Es necesaria una descripción" msgstr "A description is needed" -#: ../../../modules/web/Controllers/AccountController.php:927 +#: ../../../modules/web/Controllers/AccountController.php:926 msgid "Solicitante" msgstr "Requester" -#: ../../../modules/web/Controllers/AccountController.php:930 +#: ../../../modules/web/Controllers/AccountController.php:929 #: ../../../modules/web/Controllers/Helpers/Grid/CategoryGrid.php:106 #: ../../../modules/web/Controllers/Helpers/Grid/ClientGrid.php:105 #: ../../../modules/web/Controllers/Helpers/Grid/EventlogGrid.php:105 @@ -2837,7 +2865,7 @@ msgstr "Requester" msgid "Descripción" msgstr "Description" -#: ../../../modules/web/Controllers/AccountController.php:943 +#: ../../../modules/web/Controllers/AccountController.php:942 msgid "Solicitud realizada" msgstr "Request done" @@ -3066,7 +3094,7 @@ msgid "Ey, esto es una DEMO!!" msgstr "Ey, this is a DEMO!!" #: ../../../modules/web/Controllers/ConfigBackupController.php:86 -#: ../../../modules/web/Controllers/UserPassResetController.php:173 +#: ../../../modules/web/Controllers/UserPassResetController.php:176 #: ../../../modules/web/Forms/AccountForm.php:135 #: ../../../modules/web/Forms/UserForm.php:161 msgid "Las claves no coinciden" @@ -3951,15 +3979,11 @@ msgid "Eliminar Notificación" msgstr "Delete Notification" #: ../../../modules/web/Controllers/Helpers/Grid/PluginGrid.php:89 -#: ../../../modules/web/Controllers/Helpers/LayoutHelper.php:334 +#: ../../../modules/web/Controllers/Helpers/LayoutHelper.php:336 #: ../../../modules/web/themes/material-blue/views/plugin/index.inc:1 msgid "Plugins" msgstr "Plugins" -#: ../../../modules/web/Controllers/Helpers/Grid/PluginGrid.php:101 -msgid "Plugin" -msgstr "Plugin" - #: ../../../modules/web/Controllers/Helpers/Grid/PluginGrid.php:118 msgid "No disponible" msgstr "Unavailable" @@ -3973,7 +3997,7 @@ msgstr "Search for Plugin" #. (itstool) path: action/text #: ../../../modules/web/Controllers/Helpers/Grid/PluginGrid.php:149 #: ../../../modules/web/Controllers/Helpers/Grid/PluginGrid.php:150 -#: ../../../modules/web/Controllers/PluginController.php:120 +#: ../../../modules/web/Controllers/PluginController.php:125 #: ../../../config/actions.xml:541 msgid "Ver Plugin" msgstr "View Plugin" @@ -4224,13 +4248,13 @@ msgstr "Edit Profile" msgid "Eliminar Perfil" msgstr "Delete Profile" -#: ../../../modules/web/Controllers/Helpers/LayoutHelper.php:265 +#: ../../../modules/web/Controllers/Helpers/LayoutHelper.php:267 #: ../../../modules/web/themes/material-blue/inc/Icons.php:58 msgid "Buscar" msgstr "Search" #. (itstool) path: action/text -#: ../../../modules/web/Controllers/Helpers/LayoutHelper.php:348 +#: ../../../modules/web/Controllers/Helpers/LayoutHelper.php:350 #: ../../../modules/web/themes/material-blue/inc/Icons.php:61 #: ../../../modules/web/themes/material-blue/views/config/ldap.inc:21 #: ../../../modules/web/themes/material-blue/views/itemshow/user_profile.inc:22 @@ -4282,15 +4306,15 @@ msgstr "Value created" msgid "Valor actualizado" msgstr "Value updated" -#: ../../../modules/web/Controllers/LoginController.php:101 +#: ../../../modules/web/Controllers/LoginController.php:119 msgid "Finalizar sesión" msgstr "Logout session" -#: ../../../modules/web/Controllers/LoginController.php:103 +#: ../../../modules/web/Controllers/LoginController.php:121 msgid "Tiempo inactivo" msgstr "Inactive time" -#: ../../../modules/web/Controllers/LoginController.php:104 +#: ../../../modules/web/Controllers/LoginController.php:122 msgid "Tiempo total" msgstr "Total time" @@ -4319,18 +4343,13 @@ msgstr "Notification created" msgid "Notificación actualizada" msgstr "Notification updated" -#: ../../../modules/web/Controllers/PluginController.php:181 -#: ../../../modules/web/Controllers/PluginController.php:184 +#: ../../../modules/web/Controllers/PluginController.php:188 +#: ../../../modules/web/Controllers/PluginController.php:191 msgid "Plugin habilitado" msgstr "Plugin enabled" -#: ../../../modules/web/Controllers/PluginController.php:206 -#: ../../../modules/web/Controllers/PluginController.php:209 -msgid "Plugin deshabilitado" -msgstr "Plugin disabled" - -#: ../../../modules/web/Controllers/PluginController.php:231 -#: ../../../modules/web/Controllers/PluginController.php:234 +#: ../../../modules/web/Controllers/PluginController.php:238 +#: ../../../modules/web/Controllers/PluginController.php:241 msgid "Plugin restablecido" msgstr "Plugin reset" @@ -4357,11 +4376,11 @@ msgstr "Link deleted" msgid "Enlace creado" msgstr "Link created" -#: ../../../modules/web/Controllers/StatusController.php:94 +#: ../../../modules/web/Controllers/StatusController.php:93 msgid "Versión no disponible" msgstr "Version unavailable" -#: ../../../modules/web/Controllers/StatusController.php:142 +#: ../../../modules/web/Controllers/StatusController.php:140 msgid "Notificaciones no disponibles" msgstr "Notifications not available" @@ -4467,7 +4486,7 @@ msgstr "Request sent" msgid "En breve recibirá un correo para completar la solicitud." msgstr "You will receive an email to complete the request shortly." -#: ../../../modules/web/Controllers/UserPassResetController.php:169 +#: ../../../modules/web/Controllers/UserPassResetController.php:172 #: ../../../modules/web/Forms/AuthTokenForm.php:101 #: ../../../modules/web/Forms/UserForm.php:157 msgid "La clave no puede estar en blanco" @@ -4501,7 +4520,7 @@ msgstr "View Profile" msgid "Preferencias actualizadas" msgstr "Preferences updated" -#: ../../../modules/web/Controllers/UserSettingsManagerController.php:89 +#: ../../../modules/web/Controllers/UserSettingsManagerController.php:92 msgid "Preferencias" msgstr "Preferences" diff --git a/app/modules/web/Controllers/BootstrapController.php b/app/modules/web/Controllers/BootstrapController.php index 777b0f71..4764f4ad 100644 --- a/app/modules/web/Controllers/BootstrapController.php +++ b/app/modules/web/Controllers/BootstrapController.php @@ -43,6 +43,10 @@ final class BootstrapController extends SimpleControllerBase /** * Returns environment data + * + * @return bool + * @throws \DI\DependencyException + * @throws \DI\NotFoundException */ public function getEnvironmentAction() { @@ -103,6 +107,8 @@ final class BootstrapController extends SimpleControllerBase /** * @return bool + * @throws \DI\DependencyException + * @throws \DI\NotFoundException */ private function getAuthBasicAutologinEnabled() { @@ -112,6 +118,8 @@ final class BootstrapController extends SimpleControllerBase /** * @return string + * @throws \DI\DependencyException + * @throws \DI\NotFoundException */ private function getPublicKey() { diff --git a/app/modules/web/Controllers/ControllerBase.php b/app/modules/web/Controllers/ControllerBase.php index 9488520c..dad66d74 100644 --- a/app/modules/web/Controllers/ControllerBase.php +++ b/app/modules/web/Controllers/ControllerBase.php @@ -28,7 +28,9 @@ defined('APP_ROOT') || die(); use DI\Container; use Psr\Container\ContainerInterface; +use SP\Core\Crypt\Hash; use SP\Core\Exceptions\FileNotFoundException; +use SP\Core\Exceptions\SPException; use SP\DataModel\ProfileData; use SP\Modules\Web\Controllers\Helpers\LayoutHelper; use SP\Modules\Web\Controllers\Traits\WebControllerTrait; @@ -200,14 +202,16 @@ abstract class ControllerBase /** * Comprobar si el usuario está logado. * - * @throws \Psr\Container\ContainerExceptionInterface - * @throws \Psr\Container\NotFoundExceptionInterface + * @param bool $requireAuthCompleted + * * @throws AuthException + * @throws \DI\DependencyException + * @throws \DI\NotFoundException */ - protected function checkLoggedIn() + protected function checkLoggedIn($requireAuthCompleted = true) { if ($this->session->isLoggedIn() - && $this->session->getAuthCompleted() === true + && $this->session->getAuthCompleted() === $requireAuthCompleted ) { $browser = $this->dic->get(Browser::class); @@ -219,11 +223,37 @@ abstract class ControllerBase } } - $this->checkLoggedInSession($this->session, $this->request, function ($redirect) { - $this->router->response() - ->redirect($redirect) - ->send(true); - }); + $this->checkLoggedInSession( + $this->session, + $this->request, + function ($redirect) { + $this->router->response() + ->redirect($redirect) + ->send(true); + }, + $requireAuthCompleted + ); + } + + /** + * prepareSignedUriOnView + * + * Prepares view's variables to pass in a signed URI + */ + final protected function prepareSignedUriOnView() + { + $from = $this->request->analyzeString('from'); + + if ($from) { + try { + $this->request->verifySignature($this->configData->getPasswordSalt()); + + $this->view->assign('from', $from); + $this->view->assign('from_hash', Hash::signMessage($from, $this->configData->getPasswordSalt())); + } catch (SPException $e) { + processException($e); + } + } } /** diff --git a/app/modules/web/Controllers/Helpers/LayoutHelper.php b/app/modules/web/Controllers/Helpers/LayoutHelper.php index 63d8c395..340a89cb 100644 --- a/app/modules/web/Controllers/Helpers/LayoutHelper.php +++ b/app/modules/web/Controllers/Helpers/LayoutHelper.php @@ -191,7 +191,9 @@ final class LayoutHelper extends HelperBase // Cargar los recursos de los plugins foreach ($this->dic->get(PluginManager::class)->getLoadedPlugins() as $plugin) { - $base = str_replace(BASE_PATH, '', $plugin->getBase()); + $base = str_replace(APP_ROOT, '', $plugin->getBase()); + $base .= DIRECTORY_SEPARATOR . 'public'; + $jsResources = $plugin->getJsResources(); $cssResources = $plugin->getCssResources(); diff --git a/app/modules/web/Controllers/IndexController.php b/app/modules/web/Controllers/IndexController.php index 535def46..ab129fee 100644 --- a/app/modules/web/Controllers/IndexController.php +++ b/app/modules/web/Controllers/IndexController.php @@ -41,7 +41,9 @@ final class IndexController extends ControllerBase */ public function indexAction() { - if (!$this->session->isLoggedIn()) { + if ($this->session->isLoggedIn() === false + || $this->session->getAuthCompleted() === false + ) { $this->router->response() ->redirect('index.php?r=login'); } else { diff --git a/app/modules/web/Controllers/LoginController.php b/app/modules/web/Controllers/LoginController.php index afa459e1..74263dfc 100644 --- a/app/modules/web/Controllers/LoginController.php +++ b/app/modules/web/Controllers/LoginController.php @@ -25,11 +25,10 @@ namespace SP\Modules\Web\Controllers; use SP\Core\Context\SessionContext; -use SP\Core\Crypt\Hash; use SP\Core\Events\Event; use SP\Core\Events\EventMessage; -use SP\Core\Exceptions\SPException; use SP\Core\SessionUtil; +use SP\Http\Uri; use SP\Modules\Web\Controllers\Helpers\LayoutHelper; use SP\Modules\Web\Controllers\Traits\JsonTrait; use SP\Services\Auth\LoginService; @@ -54,30 +53,34 @@ final class LoginController extends ControllerBase try { $loginService = $this->dic->get(LoginService::class); - $from = $this->request->analyzeString('from'); - - if ($from) { - try { - $this->request->verifySignature($this->configData->getPasswordSalt(), 'from'); - - $loginService->setFrom($from); - } catch (SPException $e) { - processException($e); - } - } + $from = $this->getSignedUriFromRequest(); + $loginService->setFrom($from); $loginResponmse = $loginService->doLogin(); - $forward = $this->request->getForwardedFor(); + $this->checkForwarded(); - if ($forward !== null) { - $this->eventDispatcher->notifyEvent('login.info', - new Event($this, EventMessage::factory() - ->addDetail('Forwarded', $this->configData->isDemoEnabled() ? '***' : implode(',', $forward))) - ); - } + $redirector = function ($route) use ($from) { + $uri = new Uri('index.php'); + $uri->addParam('r', $route); - return $this->returnJsonResponseData(['url' => $loginResponmse->getRedirect()]); + if ($from !== null) { + return $uri->addParam('from', $from) + ->getUriSigned($this->configData->getPasswordSalt()); + } + + return $uri->getUri(); + }; + + $this->eventDispatcher->notifyEvent('login.finish', + new Event($this, + EventMessage::factory() + ->addData('redirect', $redirector)) + ); + + return $this->returnJsonResponseData([ + 'url' => $this->session->getTrasientKey('redirect') ?: $loginResponmse->getRedirect() + ]); } catch (\Exception $e) { processException($e); @@ -87,12 +90,27 @@ final class LoginController extends ControllerBase } } + /** + * checkForwarded + */ + private function checkForwarded() + { + $forward = $this->request->getForwardedFor(); + + if ($forward !== null) { + $this->eventDispatcher->notifyEvent('login.info', + new Event($this, EventMessage::factory() + ->addDetail('Forwarded', $this->configData->isDemoEnabled() ? '***' : implode(',', $forward))) + ); + } + } + /** * Logout action */ public function logoutAction() { - if ($this->session->isLoggedIn()) { + if ($this->session->isLoggedIn() === true) { $inactiveTime = abs(round((time() - $this->session->getLastActivity()) / 60, 2)); $totalTime = abs(round((time() - $this->session->getStartActivity()) / 60, 2)); @@ -125,30 +143,13 @@ final class LoginController extends ControllerBase */ public function indexAction() { - if ($this->session->isLoggedIn() === true) { - $this->router->response() - ->redirect('index.php?r=index') - ->send(true); - } - $this->dic->get(LayoutHelper::class) ->getCustomLayout('index', 'login'); $this->view->assign('mailEnabled', $this->configData->isMailEnabled()); // $this->view->assign('updated', SessionFactory::getAppUpdated()); - $from = $this->request->analyzeString('from'); - - if ($from) { - try { - $this->request->verifySignature($this->configData->getPasswordSalt()); - - $this->view->assign('from', $from); - $this->view->assign('from_hash', Hash::signMessage($from, $this->configData->getPasswordSalt())); - } catch (SPException $e) { - processException($e); - } - } + $this->prepareSignedUriOnView(); $this->view(); } diff --git a/app/modules/web/Controllers/PluginController.php b/app/modules/web/Controllers/PluginController.php index d1bb4b5d..eb421a29 100644 --- a/app/modules/web/Controllers/PluginController.php +++ b/app/modules/web/Controllers/PluginController.php @@ -74,6 +74,8 @@ final class PluginController extends ControllerBase * getSearchGrid * * @return $this + * @throws \DI\DependencyException + * @throws \DI\NotFoundException * @throws \SP\Core\Exceptions\ConstraintException * @throws \SP\Core\Exceptions\QueryException */ @@ -89,6 +91,9 @@ final class PluginController extends ControllerBase /** * Search action * + * @return bool + * @throws \DI\DependencyException + * @throws \DI\NotFoundException * @throws \SP\Core\Exceptions\ConstraintException * @throws \SP\Core\Exceptions\QueryException */ @@ -138,6 +143,8 @@ final class PluginController extends ControllerBase * * @param $pluginId * + * @throws \DI\DependencyException + * @throws \DI\NotFoundException * @throws \SP\Core\Exceptions\ConstraintException * @throws \SP\Core\Exceptions\QueryException * @throws \SP\Repositories\NoSuchItemException diff --git a/app/modules/web/Controllers/ResourceController.php b/app/modules/web/Controllers/ResourceController.php index f1c9a2e5..400bcd4f 100644 --- a/app/modules/web/Controllers/ResourceController.php +++ b/app/modules/web/Controllers/ResourceController.php @@ -126,6 +126,8 @@ final class ResourceController extends SimpleControllerBase /** * @throws SPException + * @throws \DI\DependencyException + * @throws \DI\NotFoundException */ protected function initialize() { diff --git a/app/modules/web/Controllers/StatusController.php b/app/modules/web/Controllers/StatusController.php index 0d320750..298eb139 100644 --- a/app/modules/web/Controllers/StatusController.php +++ b/app/modules/web/Controllers/StatusController.php @@ -25,7 +25,7 @@ namespace SP\Modules\Web\Controllers; use GuzzleHttp\Client; -use GuzzleHttp\Exception\ClientException; +use GuzzleHttp\Exception\GuzzleException; use SP\Core\AppInfoInterface; use SP\Core\Exceptions\CheckException; use SP\Http\JsonResponse; @@ -47,7 +47,6 @@ final class StatusController extends SimpleControllerBase * @return bool * @throws \DI\DependencyException * @throws \DI\NotFoundException - * @throws \GuzzleHttp\Exception\GuzzleException */ public function checkReleaseAction() { @@ -92,7 +91,7 @@ final class StatusController extends SimpleControllerBase } return $this->returnJsonResponse(JsonResponse::JSON_ERROR, __u('Versión no disponible')); - } catch (ClientException $e) { + } catch (GuzzleException $e) { processException($e); return $this->returnJsonResponseException($e); @@ -107,7 +106,6 @@ final class StatusController extends SimpleControllerBase * @return bool * @throws \DI\DependencyException * @throws \DI\NotFoundException - * @throws \GuzzleHttp\Exception\GuzzleException */ public function checkNoticesAction() { @@ -140,7 +138,7 @@ final class StatusController extends SimpleControllerBase } return $this->returnJsonResponse(JsonResponse::JSON_ERROR, __u('Notificaciones no disponibles')); - } catch (ClientException $e) { + } catch (GuzzleException $e) { processException($e); return $this->returnJsonResponseException($e); diff --git a/app/modules/web/Controllers/Traits/WebControllerTrait.php b/app/modules/web/Controllers/Traits/WebControllerTrait.php index dc31da62..89bc7caf 100644 --- a/app/modules/web/Controllers/Traits/WebControllerTrait.php +++ b/app/modules/web/Controllers/Traits/WebControllerTrait.php @@ -32,6 +32,7 @@ use SP\Core\Acl\Acl; use SP\Core\Context\ContextInterface; use SP\Core\Context\SessionContext; use SP\Core\Events\EventDispatcher; +use SP\Core\Exceptions\SPException; use SP\Core\PhpExtensionChecker; use SP\Core\UI\Theme; use SP\Http\Request; @@ -90,6 +91,37 @@ trait WebControllerTrait * @var PhpExtensionChecker */ protected $extensionChecker; + /** + * @var bool + */ + private $setup = false; + + /** + * Returns the signed URI component after validating its signature. + * This component is used for deep linking + * + * @return null|string + */ + final protected function getSignedUriFromRequest() + { + if (!$this->setup) { + return null; + } + + $from = $this->request->analyzeString('from'); + + if ($from) { + try { + $this->request->verifySignature($this->configData->getPasswordSalt(), 'from'); + } catch (SPException $e) { + processException($e); + + $from = null; + } + } + + return $from; + } /** * @param ContainerInterface $dic @@ -107,5 +139,7 @@ trait WebControllerTrait $this->request = $dic->get(Request::class); $this->acl = $dic->get(Acl::class); $this->extensionChecker = $dic->get(PhpExtensionChecker::class); + + $this->setup = true; } } \ No newline at end of file diff --git a/app/modules/web/Controllers/UserPassResetController.php b/app/modules/web/Controllers/UserPassResetController.php index 6743d6a4..d14183eb 100644 --- a/app/modules/web/Controllers/UserPassResetController.php +++ b/app/modules/web/Controllers/UserPassResetController.php @@ -139,6 +139,9 @@ final class UserPassResetController extends ControllerBase /** * @param null $hash + * + * @throws \DI\DependencyException + * @throws \DI\NotFoundException */ public function resetAction($hash = null) { diff --git a/app/modules/web/Controllers/UserSettingsManagerController.php b/app/modules/web/Controllers/UserSettingsManagerController.php index 72db626f..e3e62bbc 100644 --- a/app/modules/web/Controllers/UserSettingsManagerController.php +++ b/app/modules/web/Controllers/UserSettingsManagerController.php @@ -26,17 +26,20 @@ namespace SP\Modules\Web\Controllers; use SP\Core\Acl\Acl; use SP\Core\Events\Event; +use SP\Core\Events\EventDispatcherInterface; use SP\Core\Language; use SP\Modules\Web\Controllers\Helpers\TabsHelper; +use SP\Mvc\Controller\ExtensibleTabControllerInterface; use SP\Mvc\View\Components\DataTab; use SP\Mvc\View\Components\SelectItemAdapter; +use SP\Mvc\View\Template; /** * Class UserSettingsManagerController * * @package web\Controllers */ -final class UserSettingsManagerController extends ControllerBase +final class UserSettingsManagerController extends ControllerBase implements ExtensibleTabControllerInterface { /** * @var TabsHelper @@ -89,6 +92,38 @@ final class UserSettingsManagerController extends ControllerBase return new DataTab(__('Preferencias'), $template); } + /** + * @param DataTab $tab + */ + public function addTab(DataTab $tab) + { + $this->tabsHelper->addTab($tab); + } + + /** + * @return Template + */ + public function getView(): Template + { + return $this->view; + } + + /** + * @return void + */ + public function displayView() + { + $this->view(); + } + + /** + * @return EventDispatcherInterface + */ + public function getEventDispatcher(): EventDispatcherInterface + { + return $this->eventDispatcher; + } + /** * @throws \Psr\Container\ContainerExceptionInterface * @throws \Psr\Container\NotFoundExceptionInterface diff --git a/app/modules/web/Init.php b/app/modules/web/Init.php index f1f9c2a9..f958d6d2 100644 --- a/app/modules/web/Init.php +++ b/app/modules/web/Init.php @@ -183,7 +183,10 @@ final class Init extends ModuleBase } // Checks if the database is set up - if (!DatabaseUtil::checkDatabaseExist($this->container->get(Database::class)->getDbHandler(), $this->configData->getDbName())) { + if (!DatabaseUtil::checkDatabaseExist( + $this->container->get(Database::class)->getDbHandler(), + $this->configData->getDbName()) + ) { $this->router->response() ->redirect('index.php?r=error/databaseError') ->send(); diff --git a/composer.json b/composer.json index 8d2951af..0d777e8e 100644 --- a/composer.json +++ b/composer.json @@ -1,5 +1,5 @@ { - "name": "nuxsmin/syspass", + "name": "syspass/syspass", "description": "PHP web based Password Manager for business and personal use.", "homepage": "https://syspass.org", "minimum-stability": "stable", @@ -32,7 +32,8 @@ "ext-pdo": "*", "ext-dom": "*", "ext-gd": "*", - "ext-json": "*" + "ext-json": "*", + "ext-gettext": "*" }, "require-dev": { "phpunit/phpunit": "^6", diff --git a/lib/SP/Bootstrap.php b/lib/SP/Bootstrap.php index 26d85485..d4a25b07 100644 --- a/lib/SP/Bootstrap.php +++ b/lib/SP/Bootstrap.php @@ -40,6 +40,7 @@ use SP\Core\PhpExtensionChecker; use SP\Http\Request; use SP\Modules\Api\Init as InitApi; use SP\Modules\Web\Init as InitWeb; +use SP\Plugin\PluginManager; use SP\Services\Api\ApiRequest; use SP\Services\Api\JsonRpcResponse; use SP\Services\Upgrade\UpgradeConfigService; @@ -202,9 +203,14 @@ final class Bootstrap $controllerClass = 'SP\\Modules\\' . ucfirst(APP_MODULE) . '\\Controllers\\' . ucfirst($controller) . 'Controller'; + $this->initializePluginClasses(); + if (!method_exists($controllerClass, $method)) { logger($controllerClass . '::' . $method); + /** @var Response $response */ + $response->code(404); + throw new RuntimeException($oops); } @@ -223,6 +229,11 @@ final class Bootstrap } catch (\Exception $e) { processException($e); + /** @var Response $response */ + if ($response->status()->getCode() !== 404) { + $response->code(503); + } + return __($e->getMessage()); } } @@ -410,6 +421,18 @@ final class Bootstrap } } + /** + * initializePluginClasses + */ + protected function initializePluginClasses() + { + $loader = require APP_ROOT . DIRECTORY_SEPARATOR . 'vendor' . DIRECTORY_SEPARATOR . 'autoload.php'; + + foreach (PluginManager::getPlugins() as $name => $base) { + $loader->addPsr4($base['namespace'], $base['dir']); + } + } + /** * @return ContainerInterface */ diff --git a/lib/SP/Core/Context/ContextInterface.php b/lib/SP/Core/Context/ContextInterface.php index 64ac9705..4b4dc439 100644 --- a/lib/SP/Core/Context/ContextInterface.php +++ b/lib/SP/Core/Context/ContextInterface.php @@ -188,4 +188,21 @@ interface ContextInterface * @param string $password */ public function setTemporaryMasterPass(string $password); + + /** + * @param string $pluginName + * @param string $key + * @param mixed $value + * + * @return mixed + */ + public function setPluginKey(string $pluginName, string $key, $value); + + /** + * @param string $pluginName + * @param string $key + * + * @return mixed + */ + public function getPluginKey(string $pluginName, string $key); } \ No newline at end of file diff --git a/lib/SP/Core/Context/SessionContext.php b/lib/SP/Core/Context/SessionContext.php index 217a33c9..e5ff4f86 100644 --- a/lib/SP/Core/Context/SessionContext.php +++ b/lib/SP/Core/Context/SessionContext.php @@ -39,7 +39,7 @@ use SP\Services\User\UserLoginResponse; final class SessionContext extends ContextBase { const MAX_SID_TIME = 120; - + private static $isReset = false; private static $isLocked = false; @@ -549,4 +549,39 @@ final class SessionContext extends ContextBase $this->setContextReference($_SESSION); } + + /** + * @param string $ctxKeyName + * @param string $key + * @param mixed $value + * + * @return mixed + */ + public function setPluginKey(string $ctxKeyName, string $key, $value) + { + /** @var ContextCollection $ctxKey */ + $ctxKey = $this->getContextKey($ctxKeyName, new ContextCollection()); + + $this->setContextKey($ctxKeyName, $ctxKey->set($key, $value)); + + return $value; + } + + /** + * @param string $ctxKeyName + * @param string $key + * + * @return mixed + */ + public function getPluginKey(string $ctxKeyName, string $key) + { + /** @var ContextCollection $ctxKey */ + $ctxKey = $this->getContextKey($ctxKeyName); + + if ($ctxKey !== null) { + return $ctxKey->get($key); + } + + return null; + } } diff --git a/lib/SP/Core/Context/StatelessContext.php b/lib/SP/Core/Context/StatelessContext.php index c3c015c1..5652e8e2 100644 --- a/lib/SP/Core/Context/StatelessContext.php +++ b/lib/SP/Core/Context/StatelessContext.php @@ -269,4 +269,37 @@ final class StatelessContext extends ContextBase { $this->setTrasientKey('_tempmasterpass', $password); } + + /** + * @param string $pluginName + * @param string $key + * @param mixed $value + * + * @return mixed + */ + public function setPluginKey(string $pluginName, string $key, $value) + { + $ctxKey = $this->getContextKey('plugins'); + + $ctxKey[$pluginName][$key] = $value; + + return $value; + } + + /** + * @param string $pluginName + * @param string $key + * + * @return mixed + */ + public function getPluginKey(string $pluginName, string $key) + { + $ctxKey = $this->getContextKey('plugins'); + + if (isset($ctxKey[$pluginName][$key])) { + return $ctxKey[$pluginName][$key]; + } + + return null; + } } \ No newline at end of file diff --git a/lib/SP/Core/Events/Event.php b/lib/SP/Core/Events/Event.php index 80edc9ed..fd9983e5 100644 --- a/lib/SP/Core/Events/Event.php +++ b/lib/SP/Core/Events/Event.php @@ -25,6 +25,7 @@ namespace SP\Core\Events; use InvalidArgumentException; +use SP\Core\Exceptions\InvalidClassException; /** * Class Event @@ -61,10 +62,24 @@ final class Event } /** + * @param null $type + * * @return object + * @throws InvalidClassException */ - public function getSource() + public function getSource($type = null) { + if ($type !== null + && ($source = get_class($this->source)) !== $type + && !is_subclass_of($this->source, $type) + ) { + throw new InvalidClassException( + 'Source type mismatch', + InvalidClassException::ERROR, + sprintf('Source: %s - Expected: %s', $source, $type) + ); + } + return $this->source; } diff --git a/lib/SP/Core/Events/EventDispatcherBase.php b/lib/SP/Core/Events/EventDispatcherBase.php index 771a733f..98b88092 100644 --- a/lib/SP/Core/Events/EventDispatcherBase.php +++ b/lib/SP/Core/Events/EventDispatcherBase.php @@ -111,12 +111,16 @@ abstract class EventDispatcherBase implements EventDispatcherInterface public function notifyEvent($eventType, Event $event) { foreach ($this->observers as $observer) { - $events = $observer->getEventsString(); + if (method_exists($observer, 'getEventsString')) { + $events = $observer->getEventsString(); - if (!empty($events) - && ($events === '*' || preg_match('/' . $events . '/i', $eventType)) - ) { - // FIXME: update receivers Event + if (!empty($events) + && ($events === '*' || preg_match('/' . $events . '/i', $eventType)) + ) { + // FIXME: update receivers Event + $observer->updateEvent($eventType, $event); + } + } else { $observer->updateEvent($eventType, $event); } } diff --git a/lib/SP/Html/Minify.php b/lib/SP/Html/Minify.php index e89dfe03..1beee474 100644 --- a/lib/SP/Html/Minify.php +++ b/lib/SP/Html/Minify.php @@ -220,7 +220,7 @@ final class Minify $this->addFile($filename, $minify); } } else { - throw new \RuntimeException('Invalid string format'); + $this->addFile($files, $minify); } return $this; diff --git a/lib/SP/Http/Request.php b/lib/SP/Http/Request.php index df21d811..4d6c454f 100644 --- a/lib/SP/Http/Request.php +++ b/lib/SP/Http/Request.php @@ -374,8 +374,11 @@ final class Request public function verifySignature(string $key, string $param = null) { $result = false; + $hash = $this->params->get('h'); - if (($hash = $this->params->get('h')) !== null) { + if ($hash !== null) { + // Strips out the hash param from the URI to get the + // route which will be checked against the computed HMAC if ($param === null) { $uri = str_replace('&h=' . $hash, '', $this->request->uri()); $uri = substr($uri, strpos($uri, '?') + 1); diff --git a/lib/SP/Mvc/Controller/ControllerTrait.php b/lib/SP/Mvc/Controller/ControllerTrait.php index bfabd6e7..a3b8a608 100644 --- a/lib/SP/Mvc/Controller/ControllerTrait.php +++ b/lib/SP/Mvc/Controller/ControllerTrait.php @@ -25,6 +25,7 @@ namespace SP\Mvc\Controller; use SP\Core\Context\ContextInterface; +use SP\Core\Context\SessionContext; use SP\Core\Exceptions\SPException; use SP\Http\Json; use SP\Http\JsonResponse; @@ -53,13 +54,19 @@ trait ControllerTrait /** * Comprobar si la sesión está activa * - * @param ContextInterface $context - * @param Request $request - * @param \Closure $onRedirect + * @param SessionContext $context + * @param Request $request + * @param \Closure $onRedirect + * @param bool $requireAuthCompleted */ - protected function checkLoggedInSession(ContextInterface $context, Request $request, \Closure $onRedirect) + protected function checkLoggedInSession(SessionContext $context, + Request $request, + \Closure $onRedirect, + $requireAuthCompleted = true) { - if (!$context->isLoggedIn()) { + if ($context->isLoggedIn() === false + || $context->getAuthCompleted() !== $requireAuthCompleted + ) { if ($request->isJson()) { $jsonResponse = new JsonResponse(__u('La sesión no se ha iniciado o ha caducado')); $jsonResponse->setStatus(10); @@ -69,6 +76,9 @@ trait ControllerTrait Util::logout(); } else { try { + // Analyzes if there is any direct route within the URL + // then it computes the route HMAC to build a signed URI + // which would be used during logging in $route = $request->analyzeString('r'); $hash = $request->analyzeString('h'); diff --git a/lib/SP/Mvc/Controller/ExtensibleControllerInterface.php b/lib/SP/Mvc/Controller/ExtensibleControllerInterface.php new file mode 100644 index 00000000..43cd28da --- /dev/null +++ b/lib/SP/Mvc/Controller/ExtensibleControllerInterface.php @@ -0,0 +1,52 @@ +. + */ + +namespace SP\Mvc\Controller; + + +use SP\Core\Events\EventDispatcherInterface; +use SP\Mvc\View\Template; + +/** + * Interface ExtensibleController + * + * @package SP\Mvc\Controller + */ +interface ExtensibleControllerInterface +{ + /** + * @return Template + */ + public function getView(): Template; + + /** + * @return void + */ + public function displayView(); + + /** + * @return EventDispatcherInterface + */ + public function getEventDispatcher(): EventDispatcherInterface; +} \ No newline at end of file diff --git a/lib/SP/Mvc/Controller/ExtensibleTabControllerInterface.php b/lib/SP/Mvc/Controller/ExtensibleTabControllerInterface.php new file mode 100644 index 00000000..38ec2977 --- /dev/null +++ b/lib/SP/Mvc/Controller/ExtensibleTabControllerInterface.php @@ -0,0 +1,40 @@ +. + */ + +namespace SP\Mvc\Controller; + +use SP\Mvc\View\Components\DataTab; + +/** + * Interface ExtensibleTabController + * + * @package SP\Mvc\Controller + */ +interface ExtensibleTabControllerInterface extends ExtensibleControllerInterface +{ + /** + * @param DataTab $tab + */ + public function addTab(DataTab $tab); +} \ No newline at end of file diff --git a/lib/SP/Mvc/View/Template.php b/lib/SP/Mvc/View/Template.php index e12218d5..e001a692 100644 --- a/lib/SP/Mvc/View/Template.php +++ b/lib/SP/Mvc/View/Template.php @@ -112,10 +112,14 @@ final class Template */ private function checkTemplate($template, $base = null) { - if (null === $base && null === $this->base) { + $base = null !== $base ? $base : (null !== $this->base ? $this->base : null); + + if ($base === null) { $templateFile = $this->theme->getViewsPath() . DIRECTORY_SEPARATOR . $template . self::TEMPLATE_EXTENSION; + } elseif (is_dir($base)) { + $templateFile = $base . DIRECTORY_SEPARATOR . $template . self::TEMPLATE_EXTENSION; } else { - $templateFile = $this->theme->getViewsPath() . DIRECTORY_SEPARATOR . (null === $base ? $this->base : $base) . DIRECTORY_SEPARATOR . $template . self::TEMPLATE_EXTENSION; + $templateFile = $this->theme->getViewsPath() . DIRECTORY_SEPARATOR . $base . DIRECTORY_SEPARATOR . $template . self::TEMPLATE_EXTENSION; } if (!is_readable($templateFile)) { @@ -338,7 +342,7 @@ final class Template public function render() { if (count($this->templates) === 0) { - throw new FileNotFoundException(__u('La plantilla no contiene archivos')); + throw new FileNotFoundException(__('La plantilla no contiene archivos')); } extract($this->vars, EXTR_SKIP); diff --git a/lib/SP/Plugin/PluginBase.php b/lib/SP/Plugin/PluginBase.php index 8eb9d93b..b069a0f2 100644 --- a/lib/SP/Plugin/PluginBase.php +++ b/lib/SP/Plugin/PluginBase.php @@ -2,8 +2,8 @@ /** * sysPass * - * @author nuxsmin - * @link https://syspass.org + * @author nuxsmin + * @link https://syspass.org * @copyright 2012-2018, Rubén Domínguez nuxsmin@$syspass.org * * This file is part of sysPass. @@ -24,6 +24,9 @@ namespace SP\Plugin; +use Psr\Container\ContainerInterface; +use SP\Services\Plugin\PluginService; + /** * Class PluginBase * @@ -51,13 +54,20 @@ abstract class PluginBase implements PluginInterface * @var int */ protected $enabled; + /** + * @var PluginService + */ + private $pluginService; /** * PluginBase constructor. + * + * @param ContainerInterface $dic */ - public final function __construct() + public final function __construct(ContainerInterface $dic) { - $this->init(); + $this->pluginService = $dic->get(PluginService::class); + $this->init($dic); } /** @@ -76,14 +86,6 @@ abstract class PluginBase implements PluginInterface $this->type = $type; } - /** - * @return string - */ - public function getBase() - { - return $this->base; - } - /** * @return string */ @@ -100,14 +102,6 @@ abstract class PluginBase implements PluginInterface return $this->data; } - /** - * @param mixed $data - */ - public function setData($data) - { - $this->data = $data; - } - /** * @return int */ @@ -124,6 +118,19 @@ abstract class PluginBase implements PluginInterface $this->enabled = (int)$enabled; } + /** + * @throws \SP\Core\Exceptions\ConstraintException + * @throws \SP\Core\Exceptions\QueryException + * @throws \SP\Repositories\NoSuchItemException + */ + final public function saveData() + { + $pluginData = $this->pluginService->getByName($this->getName()); + $pluginData->setData(serialize($this->data)); + + return $this->pluginService->update($pluginData); + } + /** * Establecer las locales del plugin */ @@ -135,4 +142,12 @@ abstract class PluginBase implements PluginInterface bindtextdomain($name, $locales); bind_textdomain_codeset($name, 'UTF-8'); } + + /** + * @return string + */ + public function getBase() + { + return $this->base; + } } \ No newline at end of file diff --git a/lib/SP/Plugin/PluginEventReceiver.php b/lib/SP/Plugin/PluginEventReceiver.php index 6171124e..fc04e8c9 100644 --- a/lib/SP/Plugin/PluginEventReceiver.php +++ b/lib/SP/Plugin/PluginEventReceiver.php @@ -24,6 +24,7 @@ namespace SP\Plugin; +use Psr\Container\ContainerInterface; use SP\Core\Events\Event; use SplObserver; @@ -36,8 +37,10 @@ interface PluginEventReceiver extends SplObserver { /** * Inicialización del observador + * + * @param ContainerInterface $dic */ - public function init(); + public function init(ContainerInterface $dic); /** * Evento de actualización diff --git a/lib/SP/Plugin/PluginInterface.php b/lib/SP/Plugin/PluginInterface.php index 90a78eaf..a4d4d1c9 100644 --- a/lib/SP/Plugin/PluginInterface.php +++ b/lib/SP/Plugin/PluginInterface.php @@ -24,6 +24,8 @@ namespace SP\Plugin; +use SP\DataModel\PluginData; + /** * Interface PluginInterface * @@ -86,9 +88,9 @@ interface PluginInterface extends PluginEventReceiver public function getData(); /** - * @param mixed $data + * @param PluginData $pluginData */ - public function setData($data); + public function onLoadData(PluginData $pluginData); /** * @return int diff --git a/lib/SP/Plugin/PluginManager.php b/lib/SP/Plugin/PluginManager.php index 75e0c984..9a4f8a22 100644 --- a/lib/SP/Plugin/PluginManager.php +++ b/lib/SP/Plugin/PluginManager.php @@ -25,12 +25,16 @@ namespace SP\Plugin; use ReflectionClass; +use SP\Bootstrap; use SP\Core\Context\ContextInterface; use SP\Core\Events\Event; use SP\Core\Events\EventDispatcher; use SP\Core\Events\EventMessage; +use SP\Core\Exceptions\ConstraintException; +use SP\Core\Exceptions\QueryException; use SP\DataModel\PluginData; use SP\Repositories\NoSuchItemException; +use SP\Services\Install\Installer; use SP\Services\Plugin\PluginService; /** @@ -40,6 +44,10 @@ use SP\Services\Plugin\PluginService; */ final class PluginManager { + /** + * @var array + */ + private static $pluginsAvailable; /** * @var array Plugins habilitados */ @@ -77,6 +85,39 @@ final class PluginManager $this->pluginService = $pluginService; $this->context = $context; $this->eventDispatcher = $eventDispatcher; + + self::$pluginsAvailable = self::getPlugins(); + } + + /** + * Devuelve la lista de Plugins disponibles em el directorio + * + * @return array + */ + public static function getPlugins() + { + $dir = dir(PLUGINS_PATH); + $plugins = []; + + if ($dir) { + while (false !== ($entry = $dir->read())) { + $pluginDir = PLUGINS_PATH . DIRECTORY_SEPARATOR . $entry; + $pluginFile = $pluginDir . DIRECTORY_SEPARATOR . 'lib' . DIRECTORY_SEPARATOR . 'Plugin.php'; + + if (strpos($entry, '.') === false + && is_dir($pluginDir) + && file_exists($pluginFile) + ) { + logger(sprintf('Plugin found: %s', $pluginDir)); + + $plugins[$entry] = require $pluginDir . DIRECTORY_SEPARATOR . 'base.php'; + } + } + + $dir->close(); + } + + return $plugins; } /** @@ -88,35 +129,200 @@ final class PluginManager */ public function getPluginInfo($name) { - $name = ucfirst($name); + if (isset(self::$pluginsAvailable[$name])) { + return $this->loadPluginClass( + $name, + self::$pluginsAvailable[$name]['namespace'] + ); + } - $pluginClass = 'Plugins\\' . $name . '\\' . $name . 'Plugin'; + return null; + } + + /** + * Cargar un plugin + * + * @param string $name Nombre del plugin + * @param string $namespace + * + * @return PluginInterface + */ + public function loadPluginClass(string $name, string $namespace) + { + $name = ucfirst($name); if (isset($this->loadedPlugins[$name])) { return $this->loadedPlugins[$name]; } try { - $reflectionClass = new \ReflectionClass($pluginClass); + $class = $namespace . 'Plugin'; + $reflectionClass = new ReflectionClass($class); - /** @var PluginBase $plugin */ - $plugin = $reflectionClass->newInstance(); + /** @var PluginInterface $plugin */ + $plugin = $reflectionClass->newInstance(Bootstrap::getContainer()); - $this->loadedPlugins[$name] = $plugin; + // Do not load plugin's data if not compatible. + // Just return the plugin instance before disabling it + if (self::checkCompatibility($plugin) === false) { + $this->eventDispatcher->notifyEvent('plugin.load.error', + new Event($this, EventMessage::factory() + ->addDescription(sprintf(__('Versión de plugin no compatible (%s)'), implode('.', $plugin->getVersion())))) + ); - return $plugin; - } catch (\ReflectionException $e) { + $this->disabledPlugins[] = $name; + + return $plugin; + } + + $pluginData = $this->pluginService->getByName($name); + + if ($pluginData->getEnabled() === 1) { + $plugin->onLoadData($pluginData); + + return $plugin; + } else { + $this->disabledPlugins[] = $name; + } + } catch (\Exception $e) { processException($e); $this->eventDispatcher->notifyEvent('exception', new Event($e, EventMessage::factory() - ->addDescription(sprintf(__('No es posible cargar el plugin "%s"'), $name))) + ->addDescription(sprintf(__('No es posible cargar el plugin "%s"'), $name)) + ->addDescription($e->getMessage()) + ->addDetail(__u('Plugin'), $name)) ); } return null; } + /** + * @param PluginInterface $plugin + * + * @return bool + * @throws ConstraintException + * @throws NoSuchItemException + * @throws QueryException + */ + public function checkCompatibility(PluginInterface $plugin) + { + $pluginVersion = implode('.', $plugin->getCompatibleVersion()); + $appVersion = implode('.', array_slice(Installer::VERSION, 0, 2)); + + if (version_compare($pluginVersion, $appVersion) === -1) { + $this->pluginService->toggleEnabledByName($plugin->getName(), false); + + $this->eventDispatcher->notifyEvent('edit.plugin.disable', + new Event($this, EventMessage::factory() + ->addDetail(__u('Plugin deshabilitado'), $plugin->getName())) + ); + + return false; + } + + return true; + } + + /** + * Loads the available and enabled plugins + * + * @throws ConstraintException + * @throws QueryException + * @throws \SP\Core\Exceptions\SPException + */ + public function loadPlugins() + { + $available = array_keys(self::$pluginsAvailable); + $processed = []; + + // Process registered plugins in the database + foreach ($this->pluginService->getAll() as $plugin) { + $in = in_array($plugin->getName(), $available, true); + + if ($in === true) { + if ($plugin->getEnabled() === 1) { + $this->load($plugin->getName()); + } + + if ($plugin->getAvailable() === 0) { + $this->pluginService->toggleAvailable($plugin->getId(), true); + + $this->eventDispatcher->notifyEvent('edit.plugin.available', + new Event($this, EventMessage::factory() + ->addDetail(__u('Plugin disponible'), $plugin->getName())) + ); + + $this->load($plugin->getName()); + } + } else { + $this->pluginService->toggleAvailable($plugin->getId(), false); + + $this->eventDispatcher->notifyEvent('edit.plugin.unavailable', + new Event($this, EventMessage::factory() + ->addDetail(__u('Plugin no disponible'), $plugin->getName())) + ); + } + + $processed[] = $plugin->getName(); + } + + // Search for available plugins and not registered in the database + foreach (array_diff($available, $processed) as $plugin) { + $this->registerPlugin($plugin); + + $this->load($plugin); + } + } + + /** + * @param string $pluginName + */ + private function load(string $pluginName) + { + $plugin = $this->loadPluginClass( + $pluginName, + self::$pluginsAvailable[$pluginName]['namespace'] + ); + + if ($plugin !== null) { + logger(sprintf('Plugin loaded: %s', $pluginName)); + + $this->eventDispatcher->notifyEvent('plugin.load', + new Event($this, EventMessage::factory() + ->addDetail(__u('Plugin cargado'), $pluginName)) + ); + + $this->loadedPlugins[$pluginName] = $plugin; + + $this->eventDispatcher->attach($plugin); + } + } + + /** + * @param string $name + * + * @throws ConstraintException + * @throws QueryException + */ + private function registerPlugin(string $name) + { + $pluginData = new PluginData(); + $pluginData->setName($name); + $pluginData->setEnabled(false); + + $this->pluginService->create($pluginData); + + $this->eventDispatcher->notifyEvent('create.plugin', + new Event($this, EventMessage::factory() + ->addDescription(__u('Nuevo Plugin')) + ->addDetail(__u('Nombre'), $name) + )); + + $this->disabledPlugins[] = $name; + } + /** * Comprobar disponibilidad de plugins habilitados * @@ -127,6 +333,11 @@ final class PluginManager foreach ($this->getEnabledPlugins() as $plugin) { if (!in_array($plugin, $this->loadedPlugins)) { $this->pluginService->toggleAvailableByName($plugin, false); + + $this->eventDispatcher->notifyEvent('edit.plugin.unavailable', + new Event($this, EventMessage::factory() + ->addDetail(__u('Plugin deshabilitado'), $plugin->getName())) + ); } } } @@ -153,113 +364,6 @@ final class PluginManager return $this->enabledPlugins; } - /** - * Cargar los Plugins disponibles - */ - public function loadPlugins() - { - $classLoader = new \SplClassLoader('Plugins', PLUGINS_PATH); - $classLoader->register(); - - foreach ($this->getPlugins() as $name) { - if (($plugin = $this->loadPlugin($name)) !== null) { - logger('Plugin loaded: ' . $name); - - $this->eventDispatcher->attach($plugin); - } - } - } - - /** - * Devuelve la lista de Plugins disponibles em el directorio - * - * @return array - */ - public function getPlugins() - { - $pluginDirH = opendir(PLUGINS_PATH); - $plugins = []; - - if ($pluginDirH) { - while (false !== ($entry = readdir($pluginDirH))) { - $pluginDir = PLUGINS_PATH . DIRECTORY_SEPARATOR . $entry; - - if (strpos($entry, '.') === false - && is_dir($pluginDir) - && file_exists($pluginDir . DIRECTORY_SEPARATOR . $entry . 'Plugin.php') - ) { - $plugins[] = $entry; - } - } - - closedir($pluginDirH); - } - - return $plugins; - } - - /** - * Cargar un plugin - * - * @param string $name Nombre del plugin - * - * @return PluginInterface - */ - public function loadPlugin($name) - { - $name = ucfirst($name); - - if (isset($this->loadedPlugins[$name])) { - return $this->loadedPlugins[$name]; - } - - try { - $pluginClass = 'Plugins\\' . $name . '\\' . $name . 'Plugin'; - - $reflectionClass = new ReflectionClass($pluginClass); - - /** @var PluginInterface $plugin */ - $plugin = $reflectionClass->newInstance(); - - try { - $pluginData = $this->pluginService->getByName($plugin); - - if ($pluginData->getEnabled() === 1) { - if (!empty($pluginData->getData())) { - $pluginData->setData(unserialize($pluginData->getData())); - } - - return $plugin; - } else { - $this->disabledPlugins[] = $name; - } - } catch (NoSuchItemException $noSuchItemException) { - $pluginData = new PluginData(); - $pluginData->setName($name); - $pluginData->setEnabled(0); - - $this->pluginService->create($pluginData); - - $this->eventDispatcher->notifyEvent('create.plugin', - new Event($this, EventMessage::factory() - ->addDescription(__u('Nuevo Plugin')) - ->addDetail(__u('Nombre'), $name) - )); - - $this->disabledPlugins[] = $name; - } - } catch (\Exception $e) { - processException($e); - - $this->eventDispatcher->notifyEvent('exception', - new Event($e, EventMessage::factory() - ->addDescription(sprintf(__('No es posible cargar el plugin "%s"'), $name))) - ); - } - - return null; - } - /** * Devolver los plugins cargados * diff --git a/lib/SP/Providers/Log/DatabaseLogHandler.php b/lib/SP/Providers/Log/DatabaseLogHandler.php index e1aa36a5..2faebe03 100644 --- a/lib/SP/Providers/Log/DatabaseLogHandler.php +++ b/lib/SP/Providers/Log/DatabaseLogHandler.php @@ -66,6 +66,7 @@ final class DatabaseLogHandler extends Provider implements EventReceiver *

* * @return void + * @throws \SP\Core\Exceptions\InvalidClassException * @since 5.1.0 */ public function update(SplSubject $subject) @@ -78,6 +79,8 @@ final class DatabaseLogHandler extends Provider implements EventReceiver * * @param string $eventType Nombre del evento * @param Event $event Objeto del evento + * + * @throws \SP\Core\Exceptions\InvalidClassException */ public function updateEvent($eventType, Event $event) { diff --git a/lib/SP/Providers/Log/LogInterface.php b/lib/SP/Providers/Log/LogInterface.php index 04082192..bed56144 100644 --- a/lib/SP/Providers/Log/LogInterface.php +++ b/lib/SP/Providers/Log/LogInterface.php @@ -56,6 +56,7 @@ interface LogInterface 'show.authToken', 'clear.eventlog', 'clear.track', - 'unlock.track' + 'unlock.track', + 'plugin.load.error' ]; } \ No newline at end of file diff --git a/lib/SP/Services/Auth/LoginService.php b/lib/SP/Services/Auth/LoginService.php index 6bd830d9..494a8e1f 100644 --- a/lib/SP/Services/Auth/LoginService.php +++ b/lib/SP/Services/Auth/LoginService.php @@ -386,7 +386,8 @@ final class LoginService extends Service } $this->eventDispatcher->notifyEvent('login.session.load', - new Event($this, EventMessage::factory()->addDetail(__u('Usuario'), $userLoginResponse->getLogin())) + new Event($this, EventMessage::factory() + ->addDetail(__u('Usuario'), $userLoginResponse->getLogin())) ); } diff --git a/lib/SP/Util/ErrorUtil.php b/lib/SP/Util/ErrorUtil.php index 233d94c9..0ee0cd7f 100644 --- a/lib/SP/Util/ErrorUtil.php +++ b/lib/SP/Util/ErrorUtil.php @@ -54,36 +54,22 @@ final class ErrorUtil * @param \SP\Mvc\View\Template $view * @param \Exception $e * @param string $replace Template replacement + * @param bool $render */ - public static function showExceptionInView(Template $view, \Exception $e, $replace = null) - { - switch (get_class($e)) { - case UpdatedMasterPassException::class: - self::showErrorInView($view, self::ERR_UPDATE_MPASS, $replace); - break; - case UnauthorizedPageException::class: - self::showErrorInView($view, self::ERR_PAGE_NO_PERMISSION, $replace); - break; - case AccountPermissionException::class: - self::showErrorInView($view, self::ERR_ACCOUNT_NO_PERMISSION, $replace); - break; - default; - self::showErrorInView($view, self::ERR_EXCEPTION, $replace); - } - } - - /** - * Establecer la plantilla de error con el código indicado. - * - * @param \SP\Mvc\View\Template $view - * @param int $type int con el tipo de error - * @param string $replace Template replacement - */ - public static function showErrorInView(Template $view, $type, $replace = null) + public static function showExceptionInView(Template $view, + \Exception $e, + $replace = null, + $render = true) { if ($replace === null) { $view->resetTemplates(); - $view->resetContentTemplates(); + + if ($view->hashContentTemplates()) { + $view->resetContentTemplates(); + $view->addContentTemplate('error', Template::PARTIALS_DIR); + } else { + $view->addTemplate('error', Template::PARTIALS_DIR); + } } else { if ($view->hashContentTemplates()) { $view->removeContentTemplate($replace); @@ -94,6 +80,30 @@ final class ErrorUtil } } + switch (get_class($e)) { + case UpdatedMasterPassException::class: + self::showErrorInView($view, self::ERR_UPDATE_MPASS, $render); + break; + case UnauthorizedPageException::class: + self::showErrorInView($view, self::ERR_PAGE_NO_PERMISSION, $render); + break; + case AccountPermissionException::class: + self::showErrorInView($view, self::ERR_ACCOUNT_NO_PERMISSION, $render); + break; + default; + self::showErrorInView($view, self::ERR_EXCEPTION, $render); + } + } + + /** + * Establecer la plantilla de error con el código indicado. + * + * @param \SP\Mvc\View\Template $view + * @param int $type int con el tipo de error + * @param bool $render + */ + public static function showErrorInView(Template $view, $type, $render = true) + { $error = self::getErrorTypes($type); $view->append('errors', @@ -103,15 +113,15 @@ final class ErrorUtil 'hint' => $error['hint'] ]); - try { - echo $view->render(); - } catch (FileNotFoundException $e) { - processException($e); + if ($render) { + try { + echo $view->render(); + } catch (FileNotFoundException $e) { + processException($e); - echo $e->getMessage(); + echo $e->getMessage(); + } } - - die(); } /** diff --git a/lib/SP/Util/Util.php b/lib/SP/Util/Util.php index 158aa3e7..d57588aa 100644 --- a/lib/SP/Util/Util.php +++ b/lib/SP/Util/Util.php @@ -209,38 +209,45 @@ final class Util /** * Cast an object to another class, keeping the properties, but changing the methods * - * @param string $dstClass Class name + * @param string $dstClass Destination class name * @param string|object $serialized - * @param string $srcClass Nombre de la clase serializada + * @param string $srcClass Old class name for removing from private methods * * @return mixed - * @link http://blog.jasny.net/articles/a-dark-corner-of-php-class-casting/ */ public static function unserialize($dstClass, $serialized, $srcClass = null) { if (!is_object($serialized)) { - preg_match('/^O:\d+:"(?P[^"]++)"/', $serialized, $matches); + $match = preg_match_all('/O:\d+:"(?P[^"]++)"/', $serialized, $matches); - if (class_exists($matches['class']) - && $matches['class'] === $dstClass - ) { - return unserialize($serialized); + $process = false; + + if ($match) { + foreach ($matches['class'] as $class) { + if (!class_exists($class) + || $class !== $dstClass + ) { + $process = true; + } + } + + if ($process === false) { + return unserialize($serialized); + } } - // Si se indica la clase origen, se elimina el nombre - // de la clase en los métodos privados - if ($srcClass !== null) { - $serializedOut = preg_replace_callback( - '/:\d+:"\x00' . preg_quote($srcClass, '/') . '\x00(\w+)"/', - function ($matches) { - return ':' . strlen($matches[1]) . ':"' . $matches[1] . '"'; - }, - $serialized); + // Serialized data needs to be processed to change the class name + if ($process === true) { + // If source class is set, it will try to clean up the class name from private methods + if ($srcClass !== null) { + $serialized = preg_replace_callback( + '/:\d+:"\x00' . preg_quote($srcClass, '/') . '\x00(\w+)"/', + function ($matches) { + return ':' . strlen($matches[1]) . ':"' . $matches[1] . '"'; + }, + $serialized); + } - return self::castToClass($serializedOut, $dstClass); - } - - if ($matches['class'] !== $dstClass) { return self::castToClass($serialized, $dstClass); } } @@ -251,20 +258,18 @@ final class Util /** * Cast an object to another class * - * @param $object + * @param $cast * @param $class * * @return mixed */ - public static function castToClass($object, $class) + public static function castToClass($cast, $class) { - // should avoid '__PHP_Incomplete_Class'? + // TODO: should avoid '__PHP_Incomplete_Class'? - if (is_object($object)) { - return unserialize(preg_replace('/^O:\d+:"[^"]++"/', 'O:' . strlen($class) . ':"' . $class . '"', serialize($object))); - } + $cast = is_object($cast) ? serialize($cast) : $cast; - return unserialize(preg_replace('/^O:\d+:"[^"]++"/', 'O:' . strlen($class) . ':"' . $class . '"', $object)); + return unserialize(preg_replace('/O:\d+:"[^"]++"/', 'O:' . strlen($class) . ':"' . $class . '"', $cast)); } /** diff --git a/public/js/app-actions.js b/public/js/app-actions.js index 8f360844..bf28c0c5 100644 --- a/public/js/app-actions.js +++ b/public/js/app-actions.js @@ -1351,11 +1351,28 @@ sysPass.Actions = function (log) { toggle: function ($obj) { log.info("plugin:enable"); - tabs.save($obj, function () { - // Recargar para cargar/descargar el plugin - setTimeout(function () { - sysPassApp.util.redirect("index.php"); - }, 2000); + tabs.state.update($obj); + + const itemId = $obj.data("item-id"); + + const opts = sysPassApp.requests.getRequestOpts(); + opts.url = ajaxUrl.entrypoint; + opts.method = "get"; + opts.data = { + r: $obj.data("action-route") + "/" + itemId, + sk: sysPassApp.sk.get(), + isAjax: 1 + }; + + sysPassApp.requests.getActionCall(opts, function (json) { + sysPassApp.msg.out(json); + + if (json.status === 0) { + // Recargar para cargar/descargar el plugin + setTimeout(function () { + sysPassApp.util.redirect("index.php"); + }, 2000); + } }); }, reset: function ($obj) { diff --git a/public/js/app-actions.min.js b/public/js/app-actions.min.js index 42bed938..09deaefa 100644 --- a/public/js/app-actions.min.js +++ b/public/js/app-actions.min.js @@ -42,14 +42,15 @@ var b=sysPassApp.requests.getRequestOpts();b.url=e.entrypoint+"/?r="+a.data("act d.data=a.serialize());sysPassApp.requests.getActionCall(d,function(b){sysPassApp.msg.out(b);0===b.status&&f({r:a.data("action-next")+"/"+c})})},c='

'+sysPassApp.config.LANG[48]+"

";mdlDialog().show({text:c,negative:{title:sysPassApp.config.LANG[44],onClick:function(a){a.preventDefault();b(0)}},positive:{title:sysPassApp.config.LANG[43],onClick:function(a){a.preventDefault();b(1)}}})},delete:function(a){d.info("link:delete");var b='

'+ sysPassApp.config.LANG[12]+"

";mdlDialog().show({text:b,negative:{title:sysPassApp.config.LANG[44],onClick:function(a){a.preventDefault();sysPassApp.msg.error(sysPassApp.config.LANG[44])}},positive:{title:sysPassApp.config.LANG[43],onClick:function(b){b.preventDefault();b=a.data("item-id");var c=sysPassApp.requests.getRequestOpts();c.url=e.entrypoint+"?r="+a.data("action-route")+"/"+b;sysPassApp.requests.getActionCall(c,function(b){sysPassApp.msg.out(b);0===b.status&&f({r:a.data("action-next")+ "/"+a.data("account-id")})})}}})},refresh:function(a){d.info("link:refresh");g.state.update(a);var b=a.data("item-id"),c=sysPassApp.requests.getRequestOpts();c.url=e.entrypoint;c.method="get";c.data={r:a.data("action-route")+"/"+b,sk:sysPassApp.sk.get(),isAjax:1};sysPassApp.requests.getActionCall(c,function(b){sysPassApp.msg.out(b);0===b.status&&((b=a.data("action-next"))?f({r:b+"/"+a.data("account-id")}):f({r:g.state.tab.route,tabIndex:g.state.tab.index}))})}},eventlog:{clear:function(a){var b='

'+ -sysPassApp.config.LANG[20]+"

";mdlDialog().show({text:b,negative:{title:sysPassApp.config.LANG[44],onClick:function(a){a.preventDefault();sysPassApp.msg.error(sysPassApp.config.LANG[44])}},positive:{title:sysPassApp.config.LANG[43],onClick:function(b){b.preventDefault();g.save(a)}}})}},ajaxUrl:e,plugin:{toggle:function(a){d.info("plugin:enable");g.save(a,function(){setTimeout(function(){sysPassApp.util.redirect("index.php")},2E3)})},reset:function(a){d.info("plugin:reset");var b='

'+ -sysPassApp.config.LANG[58]+"

";mdlDialog().show({text:b,negative:{title:sysPassApp.config.LANG[44],onClick:function(a){a.preventDefault();sysPassApp.msg.error(sysPassApp.config.LANG[44])}},positive:{title:sysPassApp.config.LANG[43],onClick:function(b){b.preventDefault();g.save(a)}}})},search:function(a){d.info("plugin:search");m.search(a)},show:function(a){d.info("plugin:show");t.show(a)},save:function(a){d.info("plugin:save");var b=sysPassApp.requests.getRequestOpts();b.url=e.entrypoint+ -"?r="+a.data("route");b.data=a.serialize();sysPassApp.requests.getActionCall(b,function(b){sysPassApp.msg.out(b);0===b.status&&(f({r:a.data("action-next")}),$.magnificPopup.close())})},nav:function(a){d.info("plugin:nav");m.nav(a)}},notification:{check:function(a){d.info("notification:check");var b=sysPassApp.requests.getRequestOpts();b.url=e.entrypoint;b.method="get";b.data={r:a.data("action-route")+"/"+a.data("item-id"),sk:sysPassApp.sk.get(),isAjax:1};sysPassApp.requests.getActionCall(b,function(b){sysPassApp.msg.out(b); -0===b.status&&f({r:a.data("action-next")});sysPassApp.sk.set(b.csrf)})},search:function(a){d.info("notification:search");m.search(a)},show:function(a){d.info("notification:show");t.show(a)},save:function(a){d.info("notification:save");var b=sysPassApp.requests.getRequestOpts();b.url=e.entrypoint+"?r="+a.data("route");b.data=a.serialize();sysPassApp.requests.getActionCall(b,function(b){sysPassApp.msg.out(b);0===b.status&&(f({r:a.data("action-next")}),$.magnificPopup.close())})},delete:function(a){d.info("notification:delete"); -m.delete(a,function(b){var c=sysPassApp.requests.getRequestOpts();c.url=e.entrypoint;c.method="get";c.data={r:a.data("action-route")+(0===b.length?"/"+a.data("item-id"):""),items:b,sk:sysPassApp.sk.get(),isAjax:1};sysPassApp.requests.getActionCall(c,function(b){sysPassApp.msg.out(b);f({r:a.data("action-next")})})})},getActive:function(){d.info("notification:getActive");var a=sysPassApp.requests.getRequestOpts();a.url=e.entrypoint;a.method="get";a.data={r:"items/notifications",sk:sysPassApp.sk.get(), -isAjax:1};sysPassApp.requests.getActionCall(a,function(a){return a})},nav:function(a){d.info("eventlog:nav");m.nav(a)}},wiki:{show:function(a){d.info("wiki:show");var b=sysPassApp.requests.getRequestOpts();b.url=e.entrypoint;b.method="get";b.data={pageName:a.data("pagename"),actionId:a.data("action-id"),sk:sysPassApp.sk.get(),isAjax:1};sysPassApp.requests.getActionCall(b,function(a){0!==a.status?sysPassApp.msg.out(a):h(a.data.html)})}},items:{get:function(a){d.info("items:get");var b=a[0].selectize; -b.clearOptions();b.load(function(c){var d=sysPassApp.requests.getRequestOpts();d.url=e.entrypoint;d.method="get";d.data={r:a.data("action-route")+"/"+a.data("item-id"),sk:a.data("sk")};sysPassApp.requests.getActionCall(d,function(d){c(d.data);b.setValue(a.data("selected-id"),!0);sysPassApp.triggers.updateFormHash()})})},update:function(a){d.info("items:update");var b=$("#"+a.data("item-dst"))[0].selectize,c=b.getValue();b.clearOptions();b.load(function(d){var f=sysPassApp.requests.getRequestOpts(); -f.url=e.entrypoint;f.method="get";f.data={r:a.data("item-route"),sk:sysPassApp.sk.get()};sysPassApp.requests.getActionCall(f,function(a){d(a);b.setValue(c,!0)})})}},ldap:{check:function(a){d.info("ldap:check");var b=$(a.data("src")),c=sysPassApp.requests.getRequestOpts();c.url=e.entrypoint+"?r="+a.data("action-route");c.data=b.serialize()+"&sk="+sysPassApp.sk.get();sysPassApp.requests.getActionCall(c,function(a){sysPassApp.msg.out(a);0===a.status&&void 0!==a.data.template&&void 0!==a.data.items&& -h(a.data.template,{open:function(){var b=$("#ldap-results").find(".list-wrap").empty();a.data.items.forEach(function(a){b.append(sysPassApp.theme.html.getList(a.items,a.icon))})}})})},import:function(a){d.info("ldap:import");var b='

'+sysPassApp.config.LANG[57]+"

";mdlDialog().show({text:b,negative:{title:sysPassApp.config.LANG[44],onClick:function(a){a.preventDefault();sysPassApp.msg.error(sysPassApp.config.LANG[44])}},positive:{title:sysPassApp.config.LANG[43], -onClick:function(b){b=$(a.data("src"));var c=sysPassApp.requests.getRequestOpts();c.url=e.entrypoint+"?r="+a.data("action-route");c.data=b.serialize()+"&sk="+sysPassApp.sk.get();sysPassApp.requests.getActionCall(c,function(a){sysPassApp.msg.out(a)})}}})}},track:{unlock:function(a){d.info("track:unlock");var b=sysPassApp.requests.getRequestOpts();b.url=e.entrypoint;b.method="get";b.data={r:a.data("action-route")+"/"+a.data("item-id"),sk:sysPassApp.sk.get(),isAjax:1};sysPassApp.requests.getActionCall(b, -function(b){sysPassApp.msg.out(b);g.refresh(a)})},clear:function(a){d.info("track:clear");var b='

'+sysPassApp.config.LANG[71]+"

";mdlDialog().show({text:b,negative:{title:sysPassApp.config.LANG[44],onClick:function(a){a.preventDefault();sysPassApp.msg.error(sysPassApp.config.LANG[44])}},positive:{title:sysPassApp.config.LANG[43],onClick:function(b){b.preventDefault();g.save(a)}}})}}}}; +sysPassApp.config.LANG[20]+"

";mdlDialog().show({text:b,negative:{title:sysPassApp.config.LANG[44],onClick:function(a){a.preventDefault();sysPassApp.msg.error(sysPassApp.config.LANG[44])}},positive:{title:sysPassApp.config.LANG[43],onClick:function(b){b.preventDefault();g.save(a)}}})}},ajaxUrl:e,plugin:{toggle:function(a){d.info("plugin:enable");g.state.update(a);var b=a.data("item-id"),c=sysPassApp.requests.getRequestOpts();c.url=e.entrypoint;c.method="get";c.data={r:a.data("action-route")+ +"/"+b,sk:sysPassApp.sk.get(),isAjax:1};sysPassApp.requests.getActionCall(c,function(a){sysPassApp.msg.out(a);0===a.status&&setTimeout(function(){sysPassApp.util.redirect("index.php")},2E3)})},reset:function(a){d.info("plugin:reset");var b='

'+sysPassApp.config.LANG[58]+"

";mdlDialog().show({text:b,negative:{title:sysPassApp.config.LANG[44],onClick:function(a){a.preventDefault();sysPassApp.msg.error(sysPassApp.config.LANG[44])}},positive:{title:sysPassApp.config.LANG[43], +onClick:function(b){b.preventDefault();g.save(a)}}})},search:function(a){d.info("plugin:search");m.search(a)},show:function(a){d.info("plugin:show");t.show(a)},save:function(a){d.info("plugin:save");var b=sysPassApp.requests.getRequestOpts();b.url=e.entrypoint+"?r="+a.data("route");b.data=a.serialize();sysPassApp.requests.getActionCall(b,function(b){sysPassApp.msg.out(b);0===b.status&&(f({r:a.data("action-next")}),$.magnificPopup.close())})},nav:function(a){d.info("plugin:nav");m.nav(a)}},notification:{check:function(a){d.info("notification:check"); +var b=sysPassApp.requests.getRequestOpts();b.url=e.entrypoint;b.method="get";b.data={r:a.data("action-route")+"/"+a.data("item-id"),sk:sysPassApp.sk.get(),isAjax:1};sysPassApp.requests.getActionCall(b,function(b){sysPassApp.msg.out(b);0===b.status&&f({r:a.data("action-next")});sysPassApp.sk.set(b.csrf)})},search:function(a){d.info("notification:search");m.search(a)},show:function(a){d.info("notification:show");t.show(a)},save:function(a){d.info("notification:save");var b=sysPassApp.requests.getRequestOpts(); +b.url=e.entrypoint+"?r="+a.data("route");b.data=a.serialize();sysPassApp.requests.getActionCall(b,function(b){sysPassApp.msg.out(b);0===b.status&&(f({r:a.data("action-next")}),$.magnificPopup.close())})},delete:function(a){d.info("notification:delete");m.delete(a,function(b){var c=sysPassApp.requests.getRequestOpts();c.url=e.entrypoint;c.method="get";c.data={r:a.data("action-route")+(0===b.length?"/"+a.data("item-id"):""),items:b,sk:sysPassApp.sk.get(),isAjax:1};sysPassApp.requests.getActionCall(c, +function(b){sysPassApp.msg.out(b);f({r:a.data("action-next")})})})},getActive:function(){d.info("notification:getActive");var a=sysPassApp.requests.getRequestOpts();a.url=e.entrypoint;a.method="get";a.data={r:"items/notifications",sk:sysPassApp.sk.get(),isAjax:1};sysPassApp.requests.getActionCall(a,function(a){return a})},nav:function(a){d.info("eventlog:nav");m.nav(a)}},wiki:{show:function(a){d.info("wiki:show");var b=sysPassApp.requests.getRequestOpts();b.url=e.entrypoint;b.method="get";b.data= +{pageName:a.data("pagename"),actionId:a.data("action-id"),sk:sysPassApp.sk.get(),isAjax:1};sysPassApp.requests.getActionCall(b,function(a){0!==a.status?sysPassApp.msg.out(a):h(a.data.html)})}},items:{get:function(a){d.info("items:get");var b=a[0].selectize;b.clearOptions();b.load(function(c){var d=sysPassApp.requests.getRequestOpts();d.url=e.entrypoint;d.method="get";d.data={r:a.data("action-route")+"/"+a.data("item-id"),sk:a.data("sk")};sysPassApp.requests.getActionCall(d,function(d){c(d.data);b.setValue(a.data("selected-id"), +!0);sysPassApp.triggers.updateFormHash()})})},update:function(a){d.info("items:update");var b=$("#"+a.data("item-dst"))[0].selectize,c=b.getValue();b.clearOptions();b.load(function(d){var f=sysPassApp.requests.getRequestOpts();f.url=e.entrypoint;f.method="get";f.data={r:a.data("item-route"),sk:sysPassApp.sk.get()};sysPassApp.requests.getActionCall(f,function(a){d(a);b.setValue(c,!0)})})}},ldap:{check:function(a){d.info("ldap:check");var b=$(a.data("src")),c=sysPassApp.requests.getRequestOpts();c.url= +e.entrypoint+"?r="+a.data("action-route");c.data=b.serialize()+"&sk="+sysPassApp.sk.get();sysPassApp.requests.getActionCall(c,function(a){sysPassApp.msg.out(a);0===a.status&&void 0!==a.data.template&&void 0!==a.data.items&&h(a.data.template,{open:function(){var b=$("#ldap-results").find(".list-wrap").empty();a.data.items.forEach(function(a){b.append(sysPassApp.theme.html.getList(a.items,a.icon))})}})})},import:function(a){d.info("ldap:import");var b='

'+sysPassApp.config.LANG[57]+ +"

";mdlDialog().show({text:b,negative:{title:sysPassApp.config.LANG[44],onClick:function(a){a.preventDefault();sysPassApp.msg.error(sysPassApp.config.LANG[44])}},positive:{title:sysPassApp.config.LANG[43],onClick:function(b){b=$(a.data("src"));var c=sysPassApp.requests.getRequestOpts();c.url=e.entrypoint+"?r="+a.data("action-route");c.data=b.serialize()+"&sk="+sysPassApp.sk.get();sysPassApp.requests.getActionCall(c,function(a){sysPassApp.msg.out(a)})}}})}},track:{unlock:function(a){d.info("track:unlock"); +var b=sysPassApp.requests.getRequestOpts();b.url=e.entrypoint;b.method="get";b.data={r:a.data("action-route")+"/"+a.data("item-id"),sk:sysPassApp.sk.get(),isAjax:1};sysPassApp.requests.getActionCall(b,function(b){sysPassApp.msg.out(b);g.refresh(a)})},clear:function(a){d.info("track:clear");var b='

'+sysPassApp.config.LANG[71]+"

";mdlDialog().show({text:b,negative:{title:sysPassApp.config.LANG[44],onClick:function(a){a.preventDefault();sysPassApp.msg.error(sysPassApp.config.LANG[44])}}, +positive:{title:sysPassApp.config.LANG[43],onClick:function(b){b.preventDefault();g.save(a)}}})}}}}; diff --git a/public/js/app-main.js b/public/js/app-main.js index f15e6a42..440d920c 100644 --- a/public/js/app-main.js +++ b/public/js/app-main.js @@ -31,8 +31,8 @@ sysPass.Main = function () { log.info("checkPluginUpdates"); for (const plugin in oPublic.plugins) { - if (typeof oPublic.plugins.plugin.checkVersion === "function") { - oPublic.plugins.plugin.checkVersion().then(function (json) { + if (typeof oPublic.plugins[plugin].checkVersion === "function") { + oPublic.plugins[plugin].checkVersion().then(function (json) { if (json.status === 0 && json.data.plugin !== undefined) { msg.info(String.format(oPublic.config.LANG[67], json.data.plugin, json.data.remoteVersion)); } @@ -52,11 +52,13 @@ sysPass.Main = function () { for (let i = 0; i < oPublic.config.PLUGINS.length; i++) { const plugin = oPublic.config.PLUGINS[i]; - if (typeof sysPass.Plugin[plugin] === "function") { - plugins.plugin = sysPass.Plugin[plugin](); + if (typeof sysPass.Plugins[plugin] === "function") { + plugins[plugin] = sysPass.Plugins[plugin](oPublic); } } + log.info(plugins); + return plugins; }; diff --git a/public/js/app-main.min.js b/public/js/app-main.min.js index f32dce48..dd166eab 100644 --- a/public/js/app-main.min.js +++ b/public/js/app-main.min.js @@ -1,4 +1,4 @@ -sysPass.Main=function(){var k=function(){d.info("checkPluginUpdates");for(var a in b.plugins)"function"===typeof b.plugins.plugin.checkVersion&&b.plugins.plugin.checkVersion().then(function(a){0===a.status&&void 0!==a.data.plugin&&e.info(String.format(b.config.LANG[67],a.data.plugin,a.data.remoteVersion))})},l=function(){d.info("bindPassEncrypt");$("body").on("blur",":input[type=password]",function(a){a=$(this);if(!a.hasClass("passwordfield__no-pki"))try{g(a)}catch(c){d.error(c),e.error(c)}}).on("keypress", +sysPass.Main=function(){var k=function(){d.info("checkPluginUpdates");for(var a in b.plugins)"function"===typeof b.plugins[a].checkVersion&&b.plugins[a].checkVersion().then(function(a){0===a.status&&void 0!==a.data.plugin&&e.info(String.format(b.config.LANG[67],a.data.plugin,a.data.remoteVersion))})},l=function(){d.info("bindPassEncrypt");$("body").on("blur",":input[type=password]",function(a){a=$(this);if(!a.hasClass("passwordfield__no-pki"))try{g(a)}catch(c){d.error(c),e.error(c)}}).on("keypress", ":input[type=password]",function(a){if(13===a.keyCode){a.preventDefault();a=$(this);try{g(a)}catch(c){d.error(c),e.error(c)}a.closest("form").submit()}})},m=function(){d.info("initializeClipboard");if(clipboard.isSupported())$("body").on("click",".clip-pass-button",function(){var a=sysPassApp.actions.account.copyPass($(this)).done(function(a){if(0!==a.status)return e.out(a),!1;h.set(a.csrf)});!1!==a&&clipboard.copy(a.responseJSON.data.accpass).then(function(){e.ok(b.config.LANG[45])},function(a){e.error(b.config.LANG[46])})}).on("click", ".dialog-clip-button",function(){var a=$(this.dataset.clipboardTarget);clipboard.copy(a.text().replace(/\r?\n|\r/g)).then(function(){$(".dialog-text").removeClass("dialog-clip-copy");a.addClass("dialog-clip-copy")},function(a){e.error(b.config.LANG[46])})}).on("click",".clip-pass-icon",function(){clipboard.copy(sysPass.Util.decodeEntities($(this.dataset.clipboardTarget).val())).then(function(){e.ok(b.config.LANG[45])},function(a){e.error(b.config.LANG[46])})}).on("click",".clip-pass-field",function(){clipboard.copy(sysPass.Util.decodeEntities(document.getElementById(this.dataset.clipboardTarget).dataset.pass)).then(function(){e.ok(b.config.LANG[45])}, function(a){e.error(b.config.LANG[46])})});else d.warn(b.config.LANG[65])},g=function(a){d.info("encryptFormValue");var c=a.val();if(""!==c&&parseInt(a.attr("data-length"))!==c.length){if(c.length>b.config.PKI.MAX_SIZE)throw a.val(""),"Data length too big for encrypting";c=b.config.PKI.CRYPTO.encrypt(c);a.val(c);a.attr("data-length",c.length)}},p=function(){d.info("checkLogout");return"login/logout"===n("r")?(e.sticky(b.config.LANG[61],function(){b.util.redirect("index.php?r=login")}),!0):!1},h={current:"", @@ -9,4 +9,4 @@ case 100:this.ok(b);this.sticky(b);break;case 101:this.error(b);this.sticky(b);b c=sysPass.Config();c.setAppRoot(window.location.protocol+"//"+window.location.host+function(){for(var b="",c=1;c<=a.length-2;c++)b+="/"+a[c];return b}());var f=b.requests.getRequestOpts();f.url="/index.php?r=bootstrap/getEnvironment";f.method="get";f.useLoading=!1;f.data={isAjax:1};return b.requests.getActionCall(f,function(a){void 0!==a.data&&(c.setLang(a.data.lang),c.setPkiKey(a.data.pki_key),c.setPkiSize(a.data.pki_max_size),c.setCheckUpdates(a.data.check_updates),c.setCheckNotices(a.data.check_notices), c.setTimezone(a.data.timezone),c.setLocale(a.data.locale),c.setDebugEnabled(a.data.debug),c.setFileMaxSize(a.data.max_file_size),c.setFileAccountAllowedExts(a.data.files_allowed_exts),c.setFileImportAllowedExts(a.data.import_allowed_exts),c.setCookiesEnabled(a.data.cookies_enabled),c.setPlugins(a.data.plugins),c.setLoggedIn(a.data.loggedin),c.setAuthBasicAutologinEnabled(a.data.authbasic_autologin),c.initialize(),b.config=c.getConfig())}).fail(function(){e.error("Error while getting sysPass config
Please try again or check web server logs")})}, b={config:sysPass.Config().getConfig(),actions:sysPass.Actions(d),triggers:sysPass.Triggers(d),util:sysPass.Util(d),theme:{},plugins:{},sk:h,msg:e,log:d,encryptFormValue:g},n=function(a){for(var b=[],d,e=window.location.href.slice(window.location.href.indexOf("?")+1).split("&"),g=0;gform").each(function(){var a=$(this);a.find("button.btn-clear").on("click",function(b){b.preventDefault();a.trigger("reset")})})},config:function(){c.info("views:config");var a=$("#drop-import-files");if(0form").each(function(){var a=$(this);a.find("button.btn-clear").on("click",function(b){b.preventDefault();a.trigger("reset")})})},config:function(){c.info("views:config");var a=$("#drop-import-files");if(01 1 - aaeac4305c3720ad2583da0b48fe9e8772baf830 + 469d8c9e4929938ef00640f07de42d56e3b9b29b 0 0 - 1539293913 - f53ab0a1ef713674d6398b4e188e098b4090166c + 1539562721 + 70ced48a5cd70bf112f386361d4c10ac603132fe @@ -32,7 +32,7 @@ 0 - 6f2ae342398f2315be1702fa560634b8f1a3e408 + 0dcdb304c5e122e25fbbb97f5b9de17f87195c62 PDF JPG