PNG  IHDRQgAMA a cHRMz&u0`:pQ<bKGDgmIDATxwUﹻ& ^CX(J I@ "% (** BX +*i"]j(IH{~R)[~>h{}gy)I$Ij .I$I$ʊy@}x.: $I$Ii}VZPC)I$IF ^0ʐJ$I$Q^}{"r=OzI$gRZeC.IOvH eKX $IMpxsk.쒷/&r[޳<v| .I~)@$updYRa$I |M.e JaֶpSYR6j>h%IRز if&uJ)M$I vLi=H;7UJ,],X$I1AҒJ$ XY XzI@GNҥRT)E@;]K*Mw;#5_wOn~\ DC&$(A5 RRFkvIR}l!RytRl;~^ǷJj اy뷦BZJr&ӥ8Pjw~vnv X^(I;4R=P[3]J,]ȏ~:3?[ a&e)`e*P[4]T=Cq6R[ ~ޤrXR Հg(t_HZ-Hg M$ãmL5R uk*`%C-E6/%[t X.{8P9Z.vkXŐKjgKZHg(aK9ڦmKjѺm_ \#$5,)-  61eJ,5m| r'= &ڡd%-]J on Xm|{ RҞe $eڧY XYrԮ-a7RK6h>n$5AVڴi*ֆK)mѦtmr1p| q:흺,)Oi*ֺK)ܬ֦K-5r3>0ԔHjJئEZj,%re~/z%jVMڸmrt)3]J,T K֦OvԒgii*bKiNO~%PW0=dii2tJ9Jݕ{7"I P9JKTbu,%r"6RKU}Ij2HKZXJ,妝 XYrP ެ24c%i^IK|.H,%rb:XRl1X4Pe/`x&P8Pj28Mzsx2r\zRPz4J}yP[g=L) .Q[6RjWgp FIH*-`IMRaK9TXcq*I y[jE>cw%gLRԕiFCj-ďa`#e~I j,%r,)?[gp FI˨mnWX#>mʔ XA DZf9,nKҲzIZXJ,L#kiPz4JZF,I,`61%2s $,VOϚ2/UFJfy7K> X+6 STXIeJILzMfKm LRaK9%|4p9LwJI!`NsiazĔ)%- XMq>pk$-$Q2x#N ؎-QR}ᶦHZډ)J,l#i@yn3LN`;nڔ XuX5pF)m|^0(>BHF9(cզEerJI rg7 4I@z0\JIi䵙RR0s;$s6eJ,`n 䂦0a)S)A 1eJ,堌#635RIgpNHuTH_SԕqVe ` &S)>p;S$魁eKIuX`I4춒o}`m$1":PI<[v9^\pTJjriRŭ P{#{R2,`)e-`mgj~1ϣLKam7&U\j/3mJ,`F;M'䱀 .KR#)yhTq;pcK9(q!w?uRR,n.yw*UXj#\]ɱ(qv2=RqfB#iJmmL<]Y͙#$5 uTU7ӦXR+q,`I}qL'`6Kͷ6r,]0S$- [RKR3oiRE|nӦXR.(i:LDLTJjY%o:)6rxzҒqTJjh㞦I.$YR.ʼnGZ\ֿf:%55 I˼!6dKxm4E"mG_ s? .e*?LRfK9%q#uh$)i3ULRfK9yxm܌bj84$i1U^@Wbm4uJ,ҪA>_Ij?1v32[gLRD96oTaR׿N7%L2 NT,`)7&ƝL*꽙yp_$M2#AS,`)7$rkTA29_Iye"|/0t)$n XT2`YJ;6Jx".e<`$) PI$5V4]29SRI>~=@j]lp2`K9Jaai^" Ԋ29ORI%:XV5]JmN9]H;1UC39NI%Xe78t)a;Oi Ҙ>Xt"~G>_mn:%|~ޅ_+]$o)@ǀ{hgN;IK6G&rp)T2i୦KJuv*T=TOSV>(~D>dm,I*Ɛ:R#ۙNI%D>G.n$o;+#RR!.eU˽TRI28t)1LWϚ>IJa3oFbu&:tJ*(F7y0ZR ^p'Ii L24x| XRI%ۄ>S1]Jy[zL$adB7.eh4%%누>WETf+3IR:I3Xה)3אOۦSRO'ٺ)S}"qOr[B7ϙ.edG)^ETR"RtRݜh0}LFVӦDB^k_JDj\=LS(Iv─aTeZ%eUAM-0;~˃@i|l @S4y72>sX-vA}ϛBI!ݎߨWl*)3{'Y|iSlEڻ(5KtSI$Uv02,~ԩ~x;P4ցCrO%tyn425:KMlD ^4JRxSهF_}شJTS6uj+ﷸk$eZO%G*^V2u3EMj3k%)okI]dT)URKDS 7~m@TJR~荪fT"֛L \sM -0T KfJz+nإKr L&j()[E&I ߴ>e FW_kJR|!O:5/2跌3T-'|zX ryp0JS ~^F>-2< `*%ZFP)bSn"L :)+pʷf(pO3TMW$~>@~ū:TAIsV1}S2<%ޟM?@iT ,Eūoz%i~g|`wS(]oȤ8)$ ntu`өe`6yPl IzMI{ʣzʨ )IZ2= ld:5+請M$-ї;U>_gsY$ÁN5WzWfIZ)-yuXIfp~S*IZdt;t>KūKR|$#LcԀ+2\;kJ`]YǔM1B)UbG"IRߊ<xܾӔJ0Z='Y嵤 Leveg)$znV-º^3Ւof#0Tfk^Zs[*I꯳3{)ˬW4Ւ4 OdpbZRS|*I 55#"&-IvT&/윚Ye:i$ 9{LkuRe[I~_\ؠ%>GL$iY8 9ܕ"S`kS.IlC;Ҏ4x&>u_0JLr<J2(^$5L s=MgV ~,Iju> 7r2)^=G$1:3G< `J3~&IR% 6Tx/rIj3O< ʔ&#f_yXJiގNSz; Tx(i8%#4 ~AS+IjerIUrIj362v885+IjAhK__5X%nV%Iͳ-y|7XV2v4fzo_68"S/I-qbf; LkF)KSM$ Ms>K WNV}^`-큧32ŒVؙGdu,^^m%6~Nn&͓3ŒVZMsRpfEW%IwdǀLm[7W&bIRL@Q|)* i ImsIMmKmyV`i$G+R 0tV'!V)֏28vU7͒vHꦼtxꗞT ;S}7Mf+fIRHNZUkUx5SAJㄌ9MqμAIRi|j5)o*^'<$TwI1hEU^c_j?Е$%d`z cyf,XO IJnTgA UXRD }{H}^S,P5V2\Xx`pZ|Yk:$e ~ @nWL.j+ϝYb퇪bZ BVu)u/IJ_ 1[p.p60bC >|X91P:N\!5qUB}5a5ja `ubcVxYt1N0Zzl4]7­gKj]?4ϻ *[bg$)+À*x쳀ogO$~,5 زUS9 lq3+5mgw@np1sso Ӻ=|N6 /g(Wv7U;zωM=wk,0uTg_`_P`uz?2yI!b`kĸSo+Qx%!\οe|އԁKS-s6pu_(ֿ$i++T8=eY; צP+phxWQv*|p1. ά. XRkIQYP,drZ | B%wP|S5`~́@i޾ E;Չaw{o'Q?%iL{u D?N1BD!owPHReFZ* k_-~{E9b-~P`fE{AܶBJAFO wx6Rox5 K5=WwehS8 (JClJ~ p+Fi;ŗo+:bD#g(C"wA^ r.F8L;dzdIHUX݆ϞXg )IFqem%I4dj&ppT{'{HOx( Rk6^C٫O.)3:s(۳(Z?~ٻ89zmT"PLtw䥈5&b<8GZ-Y&K?e8,`I6e(֍xb83 `rzXj)F=l($Ij 2*(F?h(/9ik:I`m#p3MgLaKjc/U#n5S# m(^)=y=đx8ŬI[U]~SцA4p$-F i(R,7Cx;X=cI>{Km\ o(Tv2vx2qiiDJN,Ҏ!1f 5quBj1!8 rDFd(!WQl,gSkL1Bxg''՞^ǘ;pQ P(c_ IRujg(Wz bs#P­rz> k c&nB=q+ؔXn#r5)co*Ũ+G?7< |PQӣ'G`uOd>%Mctz# Ԫڞ&7CaQ~N'-P.W`Oedp03C!IZcIAMPUۀ5J<\u~+{9(FbbyAeBhOSܳ1 bÈT#ŠyDžs,`5}DC-`̞%r&ڙa87QWWp6e7 Rϫ/oY ꇅ Nܶըtc!LA T7V4Jsū I-0Pxz7QNF_iZgúWkG83 0eWr9 X]㾮݁#Jˢ C}0=3ݱtBi]_ &{{[/o[~ \q鯜00٩|cD3=4B_b RYb$óBRsf&lLX#M*C_L܄:gx)WΘsGSbuL rF$9';\4Ɍq'n[%p.Q`u hNb`eCQyQ|l_C>Lb꟟3hSb #xNxSs^ 88|Mz)}:](vbۢamŖ࿥ 0)Q7@0=?^k(*J}3ibkFn HjB׻NO z x}7p 0tfDX.lwgȔhԾŲ }6g E |LkLZteu+=q\Iv0쮑)QٵpH8/2?Σo>Jvppho~f>%bMM}\//":PTc(v9v!gոQ )UfVG+! 35{=x\2+ki,y$~A1iC6#)vC5^>+gǵ@1Hy٪7u;p psϰu/S <aʸGu'tD1ԝI<pg|6j'p:tպhX{o(7v],*}6a_ wXRk,O]Lܳ~Vo45rp"N5k;m{rZbΦ${#)`(Ŵg,;j%6j.pyYT?}-kBDc3qA`NWQū20/^AZW%NQ MI.X#P#,^Ebc&?XR tAV|Y.1!؅⨉ccww>ivl(JT~ u`ٵDm q)+Ri x/x8cyFO!/*!/&,7<.N,YDŽ&ܑQF1Bz)FPʛ?5d 6`kQձ λc؎%582Y&nD_$Je4>a?! ͨ|ȎWZSsv8 j(I&yj Jb5m?HWp=g}G3#|I,5v珿] H~R3@B[☉9Ox~oMy=J;xUVoj bUsl_35t-(ՃɼRB7U!qc+x4H_Qo֮$[GO<4`&č\GOc[.[*Af%mG/ ňM/r W/Nw~B1U3J?P&Y )`ѓZ1p]^l“W#)lWZilUQu`-m|xĐ,_ƪ|9i:_{*(3Gѧ}UoD+>m_?VPۅ15&}2|/pIOʵ> GZ9cmíتmnz)yߐbD >e}:) r|@R5qVSA10C%E_'^8cR7O;6[eKePGϦX7jb}OTGO^jn*媓7nGMC t,k31Rb (vyܴʭ!iTh8~ZYZp(qsRL ?b}cŨʊGO^!rPJO15MJ[c&~Z`"ѓޔH1C&^|Ш|rʼ,AwĴ?b5)tLU)F| &g٣O]oqSUjy(x<Ϳ3 .FSkoYg2 \_#wj{u'rQ>o;%n|F*O_L"e9umDds?.fuuQbIWz |4\0 sb;OvxOSs; G%T4gFRurj(֍ڑb uԖKDu1MK{1^ q; C=6\8FR艇!%\YÔU| 88m)֓NcLve C6z;o&X x59:q61Z(T7>C?gcļxѐ Z oo-08jہ x,`' ҔOcRlf~`jj".Nv+sM_]Zk g( UOPyεx%pUh2(@il0ݽQXxppx-NS( WO+轾 nFߢ3M<;z)FBZjciu/QoF 7R¥ ZFLF~#ȣߨ^<쩡ݛкvџ))ME>ώx4m#!-m!L;vv#~Y[đKmx9.[,UFS CVkZ +ߟrY٧IZd/ioi$%͝ب_ֶX3ܫhNU ZZgk=]=bbJS[wjU()*I =ώ:}-蹞lUj:1}MWm=̛ _ ¾,8{__m{_PVK^n3esw5ӫh#$-q=A̟> ,^I}P^J$qY~Q[ Xq9{#&T.^GVj__RKpn,b=`żY@^՝;z{paVKkQXj/)y TIc&F;FBG7wg ZZDG!x r_tƢ!}i/V=M/#nB8 XxЫ ^@CR<{䤭YCN)eKOSƟa $&g[i3.C6xrOc8TI;o hH6P&L{@q6[ Gzp^71j(l`J}]e6X☉#͕ ׈$AB1Vjh㭦IRsqFBjwQ_7Xk>y"N=MB0 ,C #o6MRc0|$)ف"1!ixY<B9mx `,tA>)5ػQ?jQ?cn>YZe Tisvh# GMމȇp:ԴVuږ8ɼH]C.5C!UV;F`mbBk LTMvPʍϤj?ԯ/Qr1NB`9s"s TYsz &9S%U԰> {<ؿSMxB|H\3@!U| k']$U+> |HHMLޢ?V9iD!-@x TIî%6Z*9X@HMW#?nN ,oe6?tQwڱ.]-y':mW0#!J82qFjH -`ѓ&M0u Uγmxϵ^-_\])@0Rt.8/?ٰCY]x}=sD3ojަЫNuS%U}ԤwHH>ڗjܷ_3gN q7[q2la*ArǓԖ+p8/RGM ]jacd(JhWko6ڎbj]i5Bj3+3!\j1UZLsLTv8HHmup<>gKMJj0@H%,W΃7R) ">c, xixј^ aܖ>H[i.UIHc U1=yW\=S*GR~)AF=`&2h`DzT󑓶J+?W+}C%P:|0H܆}-<;OC[~o.$~i}~HQ TvXΈr=b}$vizL4:ȰT|4~*!oXQR6Lk+#t/g lԁߖ[Jڶ_N$k*". xsxX7jRVbAAʯKҎU3)zSNN _'s?f)6X!%ssAkʱ>qƷb hg %n ~p1REGMHH=BJiy[<5 ǁJҖgKR*倳e~HUy)Ag,K)`Vw6bRR:qL#\rclK/$sh*$ 6덤 KԖc 3Z9=Ɣ=o>X Ώ"1 )a`SJJ6k(<c e{%kϊP+SL'TcMJWRm ŏ"w)qc ef꒵i?b7b('"2r%~HUS1\<(`1Wx9=8HY9m:X18bgD1u ~|H;K-Uep,, C1 RV.MR5άh,tWO8WC$ XRVsQS]3GJ|12 [vM :k#~tH30Rf-HYݺ-`I9%lIDTm\ S{]9gOڒMNCV\G*2JRŨ;Rҏ^ڽ̱mq1Eu?To3I)y^#jJw^Ńj^vvlB_⋌P4x>0$c>K†Aļ9s_VjTt0l#m>E-,,x,-W)سo&96RE XR.6bXw+)GAEvL)͞K4$p=Ũi_ѱOjb HY/+@θH9޼]Nԥ%n{ &zjT? Ty) s^ULlb,PiTf^<À] 62R^V7)S!nllS6~͝V}-=%* ʻ>G DnK<y&>LPy7'r=Hj 9V`[c"*^8HpcO8bnU`4JȪAƋ#1_\ XϘHPRgik(~G~0DAA_2p|J묭a2\NCr]M_0 ^T%e#vD^%xy-n}-E\3aS%yN!r_{ )sAw ڼp1pEAk~v<:`'ӭ^5 ArXOI驻T (dk)_\ PuA*BY]yB"l\ey hH*tbK)3 IKZ򹞋XjN n *n>k]X_d!ryBH ]*R 0(#'7 %es9??ښFC,ՁQPjARJ\Ρw K#jahgw;2$l*) %Xq5!U᢯6Re] |0[__64ch&_}iL8KEgҎ7 M/\`|.p,~`a=BR?xܐrQ8K XR2M8f ?`sgWS%" Ԉ 7R%$ N}?QL1|-эټwIZ%pvL3Hk>,ImgW7{E xPHx73RA @RS CC !\ȟ5IXR^ZxHл$Q[ŝ40 (>+ _C >BRt<,TrT {O/H+˟Pl6 I B)/VC<6a2~(XwV4gnXR ϱ5ǀHٻ?tw똤Eyxp{#WK qG%5],(0ӈH HZ])ג=K1j&G(FbM@)%I` XRg ʔ KZG(vP,<`[ Kn^ SJRsAʠ5xՅF`0&RbV tx:EaUE/{fi2;.IAwW8/tTxAGOoN?G}l L(n`Zv?pB8K_gI+ܗ #i?ޙ.) p$utc ~DžfՈEo3l/)I-U?aԅ^jxArA ΧX}DmZ@QLےbTXGd.^|xKHR{|ΕW_h] IJ`[G9{).y) 0X YA1]qp?p_k+J*Y@HI>^?gt.06Rn ,` ?);p pSF9ZXLBJPWjgQ|&)7! HjQt<| ؅W5 x W HIzYoVMGP Hjn`+\(dNW)F+IrS[|/a`K|ͻ0Hj{R,Q=\ (F}\WR)AgSG`IsnAR=|8$}G(vC$)s FBJ?]_u XRvύ6z ŨG[36-T9HzpW̞ú Xg큽=7CufzI$)ki^qk-) 0H*N` QZkk]/tnnsI^Gu't=7$ Z;{8^jB% IItRQS7[ϭ3 $_OQJ`7!]W"W,)Iy W AJA;KWG`IY{8k$I$^%9.^(`N|LJ%@$I}ֽp=FB*xN=gI?Q{٥4B)mw $Igc~dZ@G9K X?7)aK%݅K$IZ-`IpC U6$I\0>!9k} Xa IIS0H$I H ?1R.Чj:4~Rw@p$IrA*u}WjWFPJ$I➓/6#! LӾ+ X36x8J |+L;v$Io4301R20M I$-E}@,pS^ޟR[/s¹'0H$IKyfŸfVOπFT*a$I>He~VY/3R/)>d$I>28`Cjw,n@FU*9ttf$I~<;=/4RD~@ X-ѕzἱI$: ԍR a@b X{+Qxuq$IЛzo /~3\8ڒ4BN7$IҀj V]n18H$IYFBj3̵̚ja pp $Is/3R Ӻ-Yj+L;.0ŔI$Av? #!5"aʄj}UKmɽH$IjCYs?h$IDl843.v}m7UiI=&=0Lg0$I4: embe` eQbm0u? $IT!Sƍ'-sv)s#C0:XB2a w I$zbww{."pPzO =Ɔ\[ o($Iaw]`E).Kvi:L*#gР7[$IyGPI=@R 4yR~̮´cg I$I/<tPͽ hDgo 94Z^k盇΄8I56^W$I^0̜N?4*H`237}g+hxoq)SJ@p|` $I%>-hO0eO>\ԣNߌZD6R=K ~n($I$y3D>o4b#px2$yڪtzW~a $I~?x'BwwpH$IZݑnC㧄Pc_9sO gwJ=l1:mKB>Ab<4Lp$Ib o1ZQ@85b̍ S'F,Fe,^I$IjEdù{l4 8Ys_s Z8.x m"+{~?q,Z D!I$ϻ'|XhB)=…']M>5 rgotԎ 獽PH$IjIPhh)n#cÔqA'ug5qwU&rF|1E%I$%]!'3AFD/;Ck_`9 v!ٴtPV;x`'*bQa w I$Ix5 FC3D_~A_#O݆DvV?<qw+I$I{=Z8".#RIYyjǪ=fDl9%M,a8$I$Ywi[7ݍFe$s1ՋBVA?`]#!oz4zjLJo8$I$%@3jAa4(o ;p,,dya=F9ً[LSPH$IJYЉ+3> 5"39aZ<ñh!{TpBGkj}Sp $IlvF.F$I z< '\K*qq.f<2Y!S"-\I$IYwčjF$ w9 \ߪB.1v!Ʊ?+r:^!I$BϹB H"B;L'G[ 4U#5>੐)|#o0aڱ$I>}k&1`U#V?YsV x>{t1[I~D&(I$I/{H0fw"q"y%4 IXyE~M3 8XψL}qE$I[> nD?~sf ]o΁ cT6"?'_Ἣ $I>~.f|'!N?⟩0G KkXZE]ޡ;/&?k OۘH$IRۀwXӨ<7@PnS04aӶp.:@\IWQJ6sS%I$e5ڑv`3:x';wq_vpgHyXZ 3gЂ7{{EuԹn±}$I$8t;b|591nءQ"P6O5i }iR̈́%Q̄p!I䮢]O{H$IRϻ9s֧ a=`- aB\X0"+5"C1Hb?߮3x3&gşggl_hZ^,`5?ߎvĸ%̀M!OZC2#0x LJ0 Gw$I$I}<{Eb+y;iI,`ܚF:5ܛA8-O-|8K7s|#Z8a&><a&/VtbtLʌI$I$I$I$I$I$IRjDD%tEXtdate:create2022-05-31T04:40:26+00:00!Î%tEXtdate:modify2022-05-31T04:40:26+00:00|{2IENDB`Mini Shell

HOME


Mini Shell 1.0
DIR:/usr/lib/python3/dist-packages/ufw/
Upload File :
Current File : //usr/lib/python3/dist-packages/ufw/frontend.py
'''frontend.py: frontend interface for ufw'''
#
# Copyright 2008-2023 Canonical Ltd.
#
#    This program is free software: you can redistribute it and/or modify
#    it under the terms of the GNU General Public License version 3,
#    as published by the Free Software Foundation.
#
#    This program is distributed in the hope that it will be useful,
#    but WITHOUT ANY WARRANTY; without even the implied warranty of
#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#    GNU General Public License for more details.
#
#    You should have received a copy of the GNU General Public License
#    along with this program.  If not, see <http://www.gnu.org/licenses/>.
#

import os
import sys
import warnings

from ufw.common import UFWError
import ufw.util
from ufw.util import error, warn, msg
from ufw.backend_iptables import UFWBackendIptables
import ufw.parser


def parse_command(argv):
    '''Parse command. Returns tuple for action, rule, ip_version and dryrun.'''
    p = ufw.parser.UFWParser()

    # Basic commands
    for i in [
        "enable",
        "disable",
        "help",
        "--help",
        "-h",
        "version",
        "--version",
        "reload",
        "reset",
    ]:
        p.register_command(ufw.parser.UFWCommandBasic(i))

    # Application commands
    for i in ['list', 'info', 'default', 'update']:
        p.register_command(ufw.parser.UFWCommandApp(i))

    # Logging commands
    for i in ['on', 'off', 'low', 'medium', 'high', 'full']:
        p.register_command(ufw.parser.UFWCommandLogging(i))

    # Default commands
    for i in ['allow', 'deny', 'reject']:
        p.register_command(ufw.parser.UFWCommandDefault(i))

    # Status commands ('status', 'status verbose', 'status numbered')
    for i in [None, 'verbose', 'numbered']:
        p.register_command(ufw.parser.UFWCommandStatus(i))

    # Show commands
    for i in ['raw', 'before-rules', 'user-rules', 'after-rules', \
              'logging-rules', 'builtins', 'listening', 'added']:
        p.register_command(ufw.parser.UFWCommandShow(i))

    # Rule commands
    rule_commands = ['allow', 'limit', 'deny', 'reject', 'insert', 'delete',
                     'prepend']
    for i in rule_commands:
        p.register_command(ufw.parser.UFWCommandRule(i))
        p.register_command(ufw.parser.UFWCommandRouteRule(i))

    # Don't require the user to have to specify 'rule' as the command. Instead
    # insert 'rule' into the arguments if this is a rule command.
    if len(argv) > 2:
        idx = 1
        if argv[idx].lower() == "--dry-run":
            idx = 2
        if argv[idx].lower() != "default" and \
           argv[idx].lower() != "route" and \
           argv[idx].lower() in rule_commands:
            argv.insert(idx, 'rule')

    if len(argv) < 2 or ("--dry-run" in argv and len(argv) < 3):
        error("not enough args", do_exit=False)  # pragma: no cover
        raise ValueError()

    try:
        pr = p.parse_command(argv[1:])
    except UFWError as e:
        error("%s" % (e.value)) # pragma: no cover
    except Exception:
        error("Invalid syntax", do_exit=False)
        raise

    return pr


def get_command_help():
    '''Print help message'''
    help_msg = _('''
Usage: %(progname)s %(command)s

%(commands)s:
 %(enable)-31s enables the firewall
 %(disable)-31s disables the firewall
 %(default)-31s set default policy
 %(logging)-31s set logging to %(level)s
 %(allow)-31s add allow %(rule)s
 %(deny)-31s add deny %(rule)s
 %(reject)-31s add reject %(rule)s
 %(limit)-31s add limit %(rule)s
 %(delete)-31s delete %(urule)s
 %(insert)-31s insert %(urule)s at %(number)s
 %(prepend)-31s prepend %(urule)s
 %(route)-31s add route %(urule)s
 %(route-delete)-31s delete route %(urule)s
 %(route-insert)-31s insert route %(urule)s at %(number)s
 %(reload)-31s reload firewall
 %(reset)-31s reset firewall
 %(status)-31s show firewall status
 %(statusnum)-31s show firewall status as numbered list of %(rules)s
 %(statusverbose)-31s show verbose firewall status
 %(show)-31s show firewall report
 %(version)-31s display version information

%(appcommands)s:
 %(applist)-31s list application profiles
 %(appinfo)-31s show information on %(profile)s
 %(appupdate)-31s update %(profile)s
 %(appdefault)-31s set default application policy
''' % ({'progname': ufw.common.programName, \
         'command': "COMMAND", \
         'commands': "Commands", \
         'enable': "enable", \
         'disable': "disable", \
         'default': "default ARG", \
         'logging': "logging LEVEL", \
         'level': "LEVEL", \
         'allow': "allow ARGS", \
         'rule': "rule", \
         'deny': "deny ARGS", \
         'reject': "reject ARGS", \
         'limit': "limit ARGS", \
         'delete': "delete RULE|NUM", \
         'urule': "RULE", \
         'insert': "insert NUM RULE", \
         'prepend': "prepend RULE", \
         'route': "route RULE", \
         'route-delete': "route delete RULE|NUM", \
         'route-insert': "route insert NUM RULE", \
         'number': "NUM", \
         'reload': "reload", \
         'reset': "reset", \
         'status': "status", \
         'statusnum': "status numbered", \
         'rules': "RULES", \
         'statusverbose': "status verbose", \
         'show': "show ARG", \
         'version': "version", \
         'appcommands': "Application profile commands", \
         'applist': "app list", \
         'appinfo': "app info PROFILE", \
         'profile': "PROFILE", \
         'appupdate': "app update PROFILE", \
         'appdefault': "app default ARG"}))

    return (help_msg)


class UFWFrontend:
    '''UI'''
    def __init__(self, dryrun, backend_type="iptables",
                 rootdir=None, datadir=None):
        if backend_type == "iptables":
            try:
                self.backend = UFWBackendIptables(dryrun, rootdir=rootdir,
                                                  datadir=datadir)
            except Exception: # pragma: no cover
                raise
        else:
            raise UFWError("Unsupported backend type '%s'" % (backend_type))

        # Initialize input strings for translations
        self.no = _("n")
        self.yes = _("y")
        self.yes_full = _("yes")

    def set_enabled(self, enabled):
        '''Toggles ENABLED state in <config_dir>/ufw/ufw.conf and starts or
           stops running firewall.
        '''
        res = ""

        config_str = "no"
        if enabled:
            config_str = "yes"

        changed = False
        if (enabled and not self.backend.is_enabled()) or \
           (not enabled and self.backend.is_enabled()):
            changed = True

        # Update the config files when toggling enable/disable
        if changed:
            try:
                self.backend.set_default(self.backend.files['conf'], \
                                         "ENABLED", config_str)
            except UFWError as e: # pragma: no cover
                error(e.value)

        error_str = ""
        if enabled:
            try:
                self.backend.start_firewall()
            except UFWError as e: # pragma: no cover
                if changed:
                    error_str = e.value

            if error_str != "": # pragma: no cover
                # Revert config files when toggling enable/disable and
                # firewall failed to start
                try:
                    self.backend.set_default(self.backend.files['conf'], \
                                             "ENABLED", "no")
                except UFWError as e:
                    error(e.value)

                # Report the error
                error(error_str)

            res = _("Firewall is active and enabled on system startup")
        else:
            try:
                self.backend.stop_firewall()
            except UFWError as e: # pragma: no cover
                error(e.value)

            res = _("Firewall stopped and disabled on system startup")

        return res

    def set_default_policy(self, policy, direction):
        '''Sets default policy of firewall'''
        res = ""
        try:
            res = self.backend.set_default_policy(policy, direction)
            if self.backend.is_enabled():
                self.backend.stop_firewall()
                self.backend.start_firewall()
        except UFWError as e: # pragma: no cover
            error(e.value)

        return res

    def set_loglevel(self, level):
        '''Sets log level of firewall'''
        res = ""
        try:
            res = self.backend.set_loglevel(level)
        except UFWError as e: # pragma: no cover
            error(e.value)

        return res

    def get_status(self, verbose=False, show_count=False):
        '''Shows status of firewall'''
        try:
            out = self.backend.get_status(verbose, show_count)
        except UFWError as e: # pragma: no cover
            error(e.value)

        return out

    def get_show_raw(self, rules_type="raw"):
        '''Shows raw output of firewall'''
        try:
            out = self.backend.get_running_raw(rules_type)
        except UFWError as e: # pragma: no cover
            error(e.value)

        return out

    def get_show_listening(self):
        '''Shows listening services and incoming rules that might affect
           them'''
        res = ""
        try:
            d = ufw.util.parse_netstat_output(self.backend.use_ipv6())
        except Exception: # pragma: no cover
            err_msg = _("Could not get listening status")
            raise UFWError(err_msg)

        rules = self.backend.get_rules()

        protocols = list(d.keys())
        protocols.sort()
        for proto in protocols:
            if not self.backend.use_ipv6() and proto in ['tcp6', 'udp6']:
                continue # pragma: no cover
            res += "%s:\n" % (proto)
            ports = list(d[proto].keys())
            ports.sort()
            for port in ports:
                for item in d[proto][port]:
                    addr = item['laddr']
                    if not addr.startswith("127.") and \
                       not addr.startswith("::1"):
                        ifname = ""

                        res += "  %s " % port
                        if addr == "0.0.0.0" or addr == "::":
                            res += "* "
                            addr = "%s/0" % (item['laddr'])
                        else:
                            res += "%s " % addr
                            ifname = ufw.util.get_if_from_ip(addr)
                        res += "(%s)" % os.path.basename(item['exe'])

                        # Create an incoming rule since matching outgoing and
                        # forward rules doesn't make sense for this report.
                        rule = ufw.common.UFWRule(action="allow", \
                                                  protocol=proto[:3], \
                                                  dport=port, \
                                                  dst=addr,
                                                  direction="in", \
                                                  forward=False
                                                 )
                        rule.set_v6(proto.endswith("6"))

                        if ifname != "":
                            rule.set_interface("in", ifname)

                        rule.normalize()

                        # Get the non-tuple rule from get_matching(), and then
                        # add its corresponding CLI command.
                        matching = self.backend.get_matching(rule)
                        if len(matching) > 0:
                            res += "\n"
                            for i in matching:
                                if i > 0 and i - 1 < len(rules):
                                    res += "   [%2d] %s\n" % (i, \
                                        # Don't need UFWCommandRule here either
                                        ufw.parser.UFWCommandRule.get_command(\
                                          rules[i-1])
                                    )

                        res += "\n"

        if not self.backend.use_ipv6():
            ufw.util.debug("Skipping tcp6 and udp6 (IPv6 is disabled)")

        return res

    def get_show_added(self):
        '''Shows added rules to the firewall'''
        rules = self.backend.get_rules()

        out = _("Added user rules (see 'ufw status' for running firewall):")

        if len(rules) == 0:
            return out + _("\n(None)")

        added = []
        for r in self.backend.get_rules():
            if r.forward:
                rstr = "route %s" % \
                        ufw.parser.UFWCommandRouteRule.get_command(r)
            else:
                rstr = ufw.parser.UFWCommandRule.get_command(r)

            # Approximate the order the rules were added. Since rules is
            # internally rules4 + rules6, IPv6 only rules will show up after
            # other rules. In terms of rule ordering in the kernel, this is
            # an equivalent ordering.
            if rstr in added:
                continue

            added.append(rstr)
            out += "\nufw %s" % rstr

        return out

    def set_rule(self, rule, ip_version):
        '''Updates firewall with rule'''
        res = ""
        err_msg = ""
        tmp = ""
        rules = []

        if rule.dapp == "" and rule.sapp == "":
            rules.append(rule)
        else:
            tmprules = []
            try:
                if rule.remove:
                    if ip_version == "v4":
                        tmprules = self.backend.get_app_rules_from_system(
                                                                   rule, False)
                    elif ip_version == "v6":
                        tmprules = self.backend.get_app_rules_from_system(
                                                                   rule, True)
                    elif ip_version == "both":
                        tmprules = self.backend.get_app_rules_from_system(
                                                                   rule, False)
                        tmprules6 = self.backend.get_app_rules_from_system(
                                                                   rule, True)
                        # Only add rules that are different by more than v6 (we
                        # will handle 'ip_version == both' specially, below).
                        for x in tmprules:
                            for y in tmprules6:
                                prev6 = y.v6
                                y.v6 = False
                                if not x.match(y):
                                    y.v6 = prev6
                                    tmprules.append(y)
                    else:
                        err_msg = _("Invalid IP version '%s'") % (ip_version)
                        raise UFWError(err_msg)

                    # Don't process removal of non-existing application rules
                    if len(tmprules) == 0 and not self.backend.dryrun:
                        tmp = _("Could not delete non-existent rule")
                        if ip_version == "v4":
                            res = tmp
                        elif ip_version == "v6":
                            res = tmp + " (v6)"
                        elif ip_version == "both":
                            res = tmp + "\n" + tmp + " (v6)"
                        return res

                    for tmp in tmprules:
                        r = tmp.dup_rule()
                        r.remove = rule.remove
                        r.set_action(rule.action)
                        r.set_logtype(rule.logtype)
                        rules.append(r)
                else:
                    rules = self.backend.get_app_rules_from_template(rule)
                    # Reverse the order of rules for inserted or prepended
                    # rules, so they are inserted in the right order
                    if rule.position != 0:
                        rules.reverse()
            except Exception:
                raise

        count = 0
        set_error = False
        pos_err_msg = _("Invalid position '")
        num_v4 = self.backend.get_rules_count(False)
        num_v6 = self.backend.get_rules_count(True)
        for i, r in enumerate(rules):
            count = i
            if r.position > num_v4 + num_v6:
                pos_err_msg += str(r.position) + "'"
                raise UFWError(pos_err_msg)
            try:
                if self.backend.use_ipv6():
                    if ip_version == "v4":
                        if r.position == -1:  # prepend
                            begin = 0 if count == 0 and num_v4 == 0 else 1
                            r.set_position(begin)
                        elif r.position > num_v4:
                            pos_err_msg += str(r.position) + "'"
                            raise UFWError(pos_err_msg)
                        r.set_v6(False)
                        tmp = self.backend.set_rule(r)
                    elif ip_version == "v6":
                        if r.position == -1:  # prepend
                            begin = 0 if count == 0 and num_v6 == 0 else 1
                            r.set_position(begin)
                        elif r.position > num_v4:
                            r.set_position(r.position - num_v4)
                        elif r.position != 0 and r.position <= num_v4:
                            pos_err_msg += str(r.position) + "'"
                            raise UFWError(pos_err_msg)
                        r.set_v6(True)
                        tmp = self.backend.set_rule(r)
                    elif ip_version == "both":
                        user_pos = r.position # user specified position
                        r.set_v6(False)
                        if user_pos == -1:  # prepend
                            begin = 0 if count == 0 and num_v4 == 0 else 1
                            r.set_position(begin)
                        elif not r.remove and user_pos > num_v4:
                            # The user specified a v6 rule, so try to find a
                            # match in the v4 rules and use its position.
                            p = self.backend.find_other_position( \
                                user_pos - num_v4 + count, True)
                            if p > 0:
                                r.set_position(p)
                            else:
                                # If not found, then add the rule
                                r.set_position(0)
                        tmp = self.backend.set_rule(r)

                        # We need to readjust the position since the number
                        # of ipv4 rules increased
                        if not r.remove and user_pos > 0:
                            num_v4 = self.backend.get_rules_count(False)
                            r.set_position(user_pos + 1)

                        r.set_v6(True)
                        if user_pos == -1:  # prepend
                            begin = 0 if count == 0 and num_v6 == 0 else 1
                            r.set_position(begin)
                        elif not r.remove and r.position > 0 and \
                           r.position <= num_v4:
                            # The user specified a v4 rule, so try to find a
                            # match in the v6 rules and use its position.
                            p = self.backend.find_other_position(r.position, \
                                                                 False)
                            if p > 0:
                                # Subtract count since the list is reversed
                                r.set_position(p - count)
                            else:
                                # If not found, then add the rule
                                r.set_position(0)
                        if tmp != "":
                            tmp += "\n"

                        # Readjust position to send to set_rule
                        if not r.remove and r.position > num_v4 and \
                           user_pos != -1:
                            r.set_position(r.position - num_v4)

                        tmp += self.backend.set_rule(r)
                    else:
                        err_msg = _("Invalid IP version '%s'") % (ip_version)
                        raise UFWError(err_msg)
                else:
                    if r.position == -1:  # prepend
                        begin = 0 if count == 0 and num_v4 == 0 else 1
                        r.set_position(begin)
                    if ip_version == "v4" or ip_version == "both":
                        r.set_v6(False)
                        tmp = self.backend.set_rule(r)
                    elif ip_version == "v6":
                        err_msg = _("IPv6 support not enabled")
                        raise UFWError(err_msg)
                    else:
                        err_msg = _("Invalid IP version '%s'") % (ip_version)
                        raise UFWError(err_msg)
            except UFWError as e:
                err_msg = e.value
                set_error = True
                break

            if r.updated:
                warn_msg = _("Rule changed after normalization")
                warnings.warn(warn_msg)

        if not set_error:
            # Just return the last result if no error
            res += tmp
        elif len(rules) == 1:
            # If no error, and just one rule, error out
            error(err_msg) # pragma: no cover
        else:
            # If error and more than one rule, delete the successfully added
            # rules in reverse order
            undo_error = False
            indexes = list(range(count+1))
            indexes.reverse()
            for j in indexes:
                if count > 0 and rules[j]:
                    backout_rule = rules[j].dup_rule()
                    backout_rule.remove = True
                    try:
                        self.set_rule(backout_rule, ip_version)
                    except Exception:
                        # Don't fail, so we can try to backout more
                        undo_error = True
                        warn_msg = _("Could not back out rule '%s'") % \
                                     r.format_rule()
                        warn(warn_msg)

            err_msg += _("\nError applying application rules.")
            if undo_error:
                err_msg += _(" Some rules could not be unapplied.")
            else:
                err_msg += _(" Attempted rules successfully unapplied.")

            raise UFWError(err_msg)

        return res

    def delete_rule(self, number, force=False):
        '''Delete rule'''
        try:
            n = int(number)
        except Exception:
            err_msg = _("Could not find rule '%s'") % number
            raise UFWError(err_msg)

        rules = self.backend.get_rules()
        if n <= 0 or n > len(rules):
            err_msg = _("Could not find rule '%d'") % n
            raise UFWError(err_msg)

        rule = self.backend.get_rule_by_number(n)
        if not rule:
            err_msg = _("Could not find rule '%d'") % n
            raise UFWError(err_msg)

        rule.remove = True

        ip_version = "v4"
        if rule.v6:
            ip_version = "v6"

        proceed = True
        if not force:
            if rule.forward:
                rstr = "route %s" % \
                        ufw.parser.UFWCommandRouteRule.get_command(rule)
            else:
                rstr = ufw.parser.UFWCommandRule.get_command(rule)
            prompt = _("Deleting:\n %(rule)s\nProceed with operation " \
                       "(%(yes)s|%(no)s)? ") % ({'rule': rstr, \
                                                 'yes': self.yes, \
                                                 'no': self.no})
            msg(prompt, output=sys.stdout, newline=False)
            ans = sys.stdin.readline().lower().strip()
            if ans != "y" and ans != self.yes.lower() and \
               ans != self.yes_full.lower():
                proceed = False

        res = ""
        if proceed:
            res = self.set_rule(rule, ip_version)
        else:
            res = _("Aborted")

        return res

    def do_action(self, action, rule, ip_version, force=False):
        '''Perform action on rule. action, rule and ip_version are usually
           based on return values from parse_command().
        '''
        res = ""
        if action.startswith("logging-on"):
            tmp = action.split('_')
            if len(tmp) > 1:
                res = self.set_loglevel(tmp[1])
            else:
                res = self.set_loglevel("on")
        elif action == "logging-off":
            res = self.set_loglevel("off")
        elif action.startswith("default-"):
            err_msg = _("Unsupported default policy")
            tmp = action.split('-')
            if len(tmp) != 3:
                raise UFWError(err_msg)
            res = self.set_default_policy(tmp[1], tmp[2])
        elif action == "reset":
            res = self.reset(force)
        elif action == "status":
            res = self.get_status()
        elif action == "status-verbose":
            res = self.get_status(True)
        elif action.startswith("show"):
            tmp = action.split('-')[1]
            if tmp == "listening":
                res = self.get_show_listening()
            elif tmp == "added":
                res = self.get_show_added()
            else:
                res = self.get_show_raw(tmp)
        elif action == "status-numbered":
            res = self.get_status(False, True)
        elif action == "enable":
            res = self.set_enabled(True)
        elif action == "disable":
            res = self.set_enabled(False)
        elif action == "reload":
            if self.backend.is_enabled():
                self.set_enabled(False)
                self.set_enabled(True)
                res = _("Firewall reloaded")
            else:
                res = _("Firewall not enabled (skipping reload)")
        elif action.startswith("delete-"):
            res = self.delete_rule(action.split('-')[1], force)
        elif action == "allow" or action == "deny" or action == "reject" or \
             action == "limit":
            # allow case insensitive matches for application rules
            if rule.dapp != "":
                try:
                    tmp = self.backend.find_application_name(rule.dapp)
                    if tmp != rule.dapp:
                        rule.dapp = tmp
                        rule.set_port(tmp, "dst")
                except UFWError as e:
                    # allow for the profile being deleted (LP: #407810)
                    if not rule.remove: # pragma: no cover
                        error(e.value)
                    if not ufw.applications.valid_profile_name(rule.dapp):
                        err_msg = _("Invalid profile name")
                        raise UFWError(err_msg)

            if rule.sapp != "":
                try:
                    tmp = self.backend.find_application_name(rule.sapp)
                    if tmp != rule.sapp:
                        rule.sapp = tmp
                        rule.set_port(tmp, "dst")
                except UFWError as e:
                    # allow for the profile being deleted (LP: #407810)
                    if not rule.remove: # pragma: no cover
                        error(e.value)
                    if not ufw.applications.valid_profile_name(rule.sapp):
                        err_msg = _("Invalid profile name")
                        raise UFWError(err_msg)

            res = self.set_rule(rule, ip_version)
        else:
            err_msg = _("Unsupported action '%s'") % (action)
            raise UFWError(err_msg)

        return res

    def set_default_application_policy(self, policy):
        '''Sets default application policy of firewall'''
        res = ""
        try:
            res = self.backend.set_default_application_policy(policy)
        except UFWError as e: # pragma: no cover
            error(e.value)

        return res

    def get_application_list(self):
        '''Display list of known application profiles'''
        names = list(self.backend.profiles.keys())
        names.sort()
        rstr = _("Available applications:")
        for n in names:
            rstr += "\n  %s" % (n)
        return rstr

    def get_application_info(self, pname):
        '''Display information on profile'''
        names = []
        if pname == "all":
            names = list(self.backend.profiles.keys())
            names.sort()
        else:
            if not ufw.applications.valid_profile_name(pname):
                err_msg = _("Invalid profile name")
                raise UFWError(err_msg)
            names.append(pname)

        rstr = ""
        for name in names:
            if name not in self.backend.profiles or \
               not self.backend.profiles[name]:
                err_msg = _("Could not find profile '%s'") % (name)
                raise UFWError(err_msg)

            if not ufw.applications.verify_profile(name, \
               self.backend.profiles[name]):
                err_msg = _("Invalid profile")
                raise UFWError(err_msg)

            rstr += _("Profile: %s\n") % (name)
            rstr += _("Title: %s\n") % (ufw.applications.get_title(\
                                        self.backend.profiles[name]))

            rstr += _("Description: %s\n\n") % \
                                            (ufw.applications.get_description(\
                                             self.backend.profiles[name]))

            ports = ufw.applications.get_ports(self.backend.profiles[name])
            if len(ports) > 1 or ',' in ports[0]:
                rstr += _("Ports:")
            else:
                rstr += _("Port:")

            for p in ports:
                rstr += "\n  %s" % (p)

            if name != names[len(names)-1]:
                rstr += "\n\n--\n\n"

        return ufw.util.wrap_text(rstr)

    def application_update(self, profile):
        '''Refresh application profile'''
        rstr = ""
        allow_reload = True
        trigger_reload = False

        try: # pragma: no cover
            if self.backend.do_checks and ufw.util.under_ssh():
                # Don't reload the firewall if running under ssh
                allow_reload = False
        except Exception: # pragma: no cover
            # If for some reason we get an exception trying to find the parent
            # pid, err on the side of caution and don't automatically reload
            # the firewall. LP: #424528
            allow_reload = False

        if profile == "all":
            profiles = list(self.backend.profiles.keys())
            profiles.sort()
            for p in profiles:
                (tmp, found) = self.backend.update_app_rule(p)
                if found:
                    if tmp != "":
                        tmp += "\n"
                    rstr += tmp
                    trigger_reload = found
        else:
            (rstr, trigger_reload) = self.backend.update_app_rule(profile)
            if rstr != "":
                rstr += "\n"

        if trigger_reload and self.backend.is_enabled():
            if allow_reload:
                try:
                    self.backend._reload_user_rules()
                except Exception:
                    raise
                rstr += _("Firewall reloaded")
            else:
                rstr += _("Skipped reloading firewall")

        return rstr

    def application_add(self, profile):
        '''Refresh application profile'''
        rstr = ""
        policy = ""

        if profile == "all":
            err_msg = _("Cannot specify 'all' with '--add-new'")
            raise UFWError(err_msg)

        default = self.backend.defaults['default_application_policy']
        if default == "skip":
            ufw.util.debug("Policy is '%s', not adding profile '%s'" % \
                           (policy, profile))
            return rstr
        elif default == "accept":
            policy = "allow"
        elif default == "drop":
            policy = "deny"
        elif default == "reject":
            policy = "reject"
        else:
            err_msg = _("Unknown policy '%s'") % (default)
            raise UFWError(err_msg)

        args = [ 'ufw' ]
        if self.backend.dryrun:
            args.append("--dry-run")

        args += [ policy, profile ]
        try:
            pr = parse_command(args)
        except Exception: # pragma: no cover
            raise

        if 'rule' in pr.data:
            rstr = self.do_action(pr.action, pr.data['rule'], \
                                  pr.data['iptype'])
        else:
            rstr = self.do_action(pr.action, "", "")

        return rstr

    def do_application_action(self, action, profile):
        '''Perform action on profile. action and profile are usually based on
           return values from parse_command().
        '''
        res = ""
        if action == "default-allow":
            res = self.set_default_application_policy("allow")
        elif action == "default-deny":
            res = self.set_default_application_policy("deny")
        elif action == "default-reject":
            res = self.set_default_application_policy("reject")
        elif action == "default-skip":
            res = self.set_default_application_policy("skip")
        elif action == "list":
            res = self.get_application_list()
        elif action == "info":
            res = self.get_application_info(profile)
        elif action == "update" or action == "update-with-new":
            str1 = self.application_update(profile)
            str2 = ""
            if action == "update-with-new":
                str2 = self.application_add(profile)

            if str1 != "" and str2 != "":
                str1 += "\n"
            res = str1 + str2
        else:
            err_msg = _("Unsupported action '%s'") % (action)
            raise UFWError(err_msg)

        return res

    def continue_under_ssh(self):
        '''If running under ssh, prompt the user for confirmation'''
        proceed = True
        if self.backend.do_checks and ufw.util.under_ssh(): # pragma: no cover
            prompt = _("Command may disrupt existing ssh connections. " \
                       "Proceed with operation (%(yes)s|%(no)s)? ") % \
                       ({'yes': self.yes, 'no': self.no})
            msg(prompt, output=sys.stdout, newline=False)
            ans = sys.stdin.readline().lower().strip()
            if ans != "y" and ans != self.yes and ans != self.yes_full:
                proceed = False

        return proceed

    def reset(self, force=False):
        '''Reset the firewall'''
        res = ""
        prompt = _("Resetting all rules to installed defaults. Proceed with " \
                   "operation (%(yes)s|%(no)s)? ") % \
                   ({'yes': self.yes, 'no': self.no})
        if self.backend.do_checks and ufw.util.under_ssh():
            prompt = _("Resetting all rules to installed defaults. This may " \
                       "disrupt existing ssh connections. Proceed with " \
                       "operation (%(yes)s|%(no)s)? ") % \
                       ({'yes': self.yes, 'no': self.no})

        if self.backend.do_checks and not force: # pragma: no cover
            msg(ufw.util.wrap_text(prompt), output=sys.stdout, newline=False)
            ans = sys.stdin.readline().lower().strip()
            if ans != "y" and ans != self.yes and ans != self.yes_full:
                res = _("Aborted")
                return res

        if self.backend.is_enabled():
            res += self.set_enabled(False)
        res = self.backend.reset()

        return res