From ea47a2e92ce957f0f9e104290bc433f047dddd99 Mon Sep 17 00:00:00 2001 From: Micah Lee Date: Fri, 6 Aug 2021 12:57:53 -0700 Subject: [PATCH 1/5] Fix error message user interface --- dangerzone/gui/main_window.py | 34 ++++++++++++++++++++++++++++------ share/error.png | Bin 0 -> 13418 bytes 2 files changed, 28 insertions(+), 6 deletions(-) create mode 100644 share/error.png diff --git a/dangerzone/gui/main_window.py b/dangerzone/gui/main_window.py index 0378b67..9b5f2e0 100644 --- a/dangerzone/gui/main_window.py +++ b/dangerzone/gui/main_window.py @@ -423,13 +423,14 @@ class SettingsWidget(QtWidgets.QWidget): class ConvertThread(QtCore.QThread): - finished = QtCore.Signal() + finished = QtCore.Signal(bool) update = QtCore.Signal(bool, str, int) def __init__(self, global_common, common): super(ConvertThread, self).__init__() self.global_common = global_common self.common = common + self.error = False def run(self): ocr_lang = self.global_common.ocr_languages[ @@ -443,19 +444,20 @@ class ConvertThread(QtCore.QThread): ocr_lang, self.stdout_callback, ): - self.finished.emit() + self.finished.emit(self.error) def stdout_callback(self, line): try: status = json.loads(line) except: print(f"Invalid JSON returned from container: {line}") - + self.error = True self.update.emit(True, "Invalid JSON returned from container", 0) return s = Style.BRIGHT + Fore.CYAN + f"{status['percentage']}% " if status["error"]: + self.error = True s += Style.RESET_ALL + Fore.RED + status["text"] else: s += Style.RESET_ALL + status["text"] @@ -473,6 +475,8 @@ class ConvertWidget(QtWidgets.QWidget): self.gui_common = gui_common self.common = common + self.error = False + # Dangerous document label self.dangerous_doc_label = QtWidgets.QLabel() self.dangerous_doc_label.setAlignment(QtCore.Qt.AlignCenter) @@ -480,11 +484,25 @@ class ConvertWidget(QtWidgets.QWidget): "QLabel { font-size: 16px; font-weight: bold; }" ) + # Label + self.error_image = QtWidgets.QLabel() + self.error_image.setPixmap( + QtGui.QPixmap.fromImage( + QtGui.QImage(self.global_common.get_resource_path("error.png")) + ) + ) + self.error_image.hide() + self.label = QtWidgets.QLabel() self.label.setAlignment(QtCore.Qt.AlignCenter) self.label.setWordWrap(True) self.label.setStyleSheet("QLabel { font-size: 18px; }") + label_layout = QtWidgets.QHBoxLayout() + label_layout.addWidget(self.error_image) + label_layout.addWidget(self.label, stretch=1) + + # Progress bar self.progress = QtWidgets.QProgressBar() self.progress.setRange(0, 100) self.progress.setValue(0) @@ -493,7 +511,7 @@ class ConvertWidget(QtWidgets.QWidget): layout = QtWidgets.QVBoxLayout() layout.addWidget(self.dangerous_doc_label) layout.addStretch() - layout.addWidget(self.label) + layout.addLayout(label_layout) layout.addWidget(self.progress) layout.addStretch() self.setLayout(layout) @@ -512,13 +530,17 @@ class ConvertWidget(QtWidgets.QWidget): def update(self, error, text, percentage): if error: - # TODO: add error image or something - pass + self.error = True + self.error_image.show() + self.progress.hide() self.label.setText(text) self.progress.setValue(percentage) def all_done(self): + if self.error: + return + # In Windows, open Explorer with the safe PDF in focus if platform.system() == "Windows": dest_filename_windows = self.common.output_filename.replace("/", "\\") diff --git a/share/error.png b/share/error.png new file mode 100644 index 0000000000000000000000000000000000000000..270bd24a7d3dda4d800e17b1d589dd5835bea9c2 GIT binary patch literal 13418 zcmeIYWmsF?7A+jCxR&A)tXP8vcXur=g#ZD9ySo)B?z9vy4n<3Gch?pvuBEs`=}r5- z$DZ&0InVRme<#V_$)0P>vF03W?v?DU9i^@+hmApo0RRB7738Hg;qM&3H?$}4y)NSI zYXE>!!$(WcO%vh?baHXDgxNuXZr)B%Ak+(H2>^I4R=$O~PzZU1|1y8}3ULP_Ktk7w z#J;*Jp_9rK?X!aONjg!pCL^k~hm;Li_iMK!{+2!9nMqkx>Flyg<3luvclB1OVWK)f zOo;q=_nx)2y{{wCcg3%L-JAKr$7-zly2HdX2UFNYFi^>aO>6f%`R27_{Y`VgPmjEX z*btqq+Yuk*k~TKNhjZ-fX7NC(ksY0p1v!%Y+vaa-nmJ;!IcaSRkFB@&9p*GXtfyut z0jR_;a{MDF5JMjMp9%(+Uc2tZ#u58Q=AC>EzwSdDRCBI1(Sf#GZJ+a9r!RCcFl_C* z_h5FQatF3Q-ZU$Tp{_3D1y&~Cem-}szE^nFAu@hHAyA&>dUft5Vkwzrf_oVi_t;JT zSsv?pfU5&DkRXu#+H=#BN9&k=dqh>}M#R|lJrgzYipvV+r{jhF=Spt^?z?r58Kb6c zc?ee@u(TTK*m#BK~;0SiP4>Rjpg>A-2A-1XW!;Y=yK~Z^6qpPaE(e_E^pM5TYoNi z(%-vKykMkXjfqEll&$v$)1uRoIB8^@=s3o;wV6AInYYbng4N z2W98$HqqN%C`XKRVFIjBF+}ilG=Ti_rCCvg4+isx6c?7#4{1I)0y`^5An?nt^=;o*{kSW)I2 zQmZWQH2pEVI`)okL`I!g(78FCRfm^~LPz!IY%NEP_j$9b{HKMa zJAVDF`0P3VFqZO7PgH+XPRZM(8(lTYMYiA1&7zeFiLhRG+|HfTr(l-Zs?ocd)>|ht z<=u7)Cl|@5^Zh2ZqX6j9r`Al8Unbt?$D^c0M`DQr1+zaHTmyH0ysiM%jMaB7W0hh* z(;~MP`!?&pjih?Fv@nFNKRi@=-{3!Gb@n(zP9eQHY-&zn@tw(V#xB~ z=c|+g#;bx+D$hNgg+_n;6b)as!sTqd@B7YA^2JdbxQy889EqP&Pl@O6KduD)Iv7+` zOD(S+Ei-#3Y+G`xPFdIMe8+O9KvrnD-;QyuquDFrJ&aV@?+i_qjpL zwrp8pCEAAU3;M;#wd0D9j^D5N`AUkK?7!n`@Q8)q27nyw)UI3w$-hc*TKSAtb!{pq zvhmQ<%QJE6IOquyVg`?HN0|WY>YasJbL8G5J!G+J;Kf;6Nb(8YM!FC1%jS<6woO_u zZ~26yme(tO*SP&a_}!&O?F0foqg)y-JXH@4>LM9Sm+yg{Zha+)fXF}b68I!;sbZY} z()GQETY1je#Xefzm%t;7^97=7p6ldL6CjEEVo53icPKFuRsP(Ip4Py6}ePXBzb{5 zT&DK!`6CsOX0Kd51XQiOiW?2m5xNB?c}OjPXg3Y9IO6o5&mN-Nm%66X5yEvMU1-H! zmb(!kTADO9jf)Q*7qB7sF@ODt!{e)psv9s<@!y=cCGLFdA-R&4XZnOD6nfK} z@s8+oEc&X$$5tYPVrgvc9Hz2g{?b;+jYXvBOe;G;1d{Sx}RuP^qJ$Zvz?o zk33R~y_8cRf_utOq-HnlynMNcf|k9qgeA;ZGy5q|V=x>T*|2-3HC7j=A12c& zhbeQ}NVE-2Kx#gHIEp}NP5sc+bek_hZC1g~to0TSk9U!ulf}@JUusG<+V$$xpqB09 zxrv&0+#q%(1_C&e5j}FH_Grc?&@}WGfkHL9IHKs2h9Kv$iZ34~^gC&e^|(g(&iO%TR~xq0mqv{K-C#?Zt%Th;-3_{1?9XZ?z}E(MB@t|b>3$0szSy5UefG=% z2<;)qCDE^cP$XdYe!S6OcSl!n8Q9Ask9D&Bq~uBJ+0Wog$^FC>RTS&(RdJ`PzES+^ zv~siTE#p}6J~{%rtt@3*ZqdHaNY7xa+qaKo;$mNrWe^DBtmRBNUvgM0*3)g2FwlhZ zT(p6VTGiRy2#So7sI@w5H&Rkqg4S6P@AgT})SFk_fpfV9vrNW(mVBn#DvAbxE{J1V z7GD4PMNOFzgIY+PPGFE>yHr5AVB_Gm&OlteASr%44Na!%vYdi_?8L{F6X6l0c#ho}@MEyE%0}W~L9+jYu=5Cu zSG;1695P-65y&=U4wYeksy@`Ei{dppLCe-sP!uAA#$nmUy1_@N`>JM+>w-z&cx<_X zwA*|O@|T`ceh;mIT`ZaZ!^&A}?mpViut*~eYa2-?~^a23NYP6ykD3TZrk|Sm& zypSe)cxcCWQ>0CiMfNRk=t<)XNkyX_3L-143w|8LPO3^a7%8Zhjoxdilz)%x^`Z=L z8m1lYf;ihag+4Z8zBiFdj_7D=v-e`+S@Ehm*ofO$y`h1Iu6I*a`P1TJTFE z;ENxss0&X+sm2RcE`95Z9xY7kL*9?AzY)gfI68Ae1X8NUa_0Ab6RfVrh0k z=os+_f#kK=bh_o0b$HjvUxjO_JInw~(GxD-!$2IJVoZQGi^2Z1a<#x@CV{P~O?UCA zW|{>stdyEA(ivbETyKqYuw`h2HzPMF+OM*()*}2|V$Z-r!OOtT|E(M_7@G!yIpQDv zxu1>qE27nYZ@(I_2tH42XBKa&3fR~^!O8pjf*-sqC>h>ZsB0Dmq)Z6MTSGku$V z2b1K=CM0)K?aC?PHjw41vJtyCiCLb;3SO$sMp2KVv!NZ@rAnYQ9C8AQ5d-e(%tz4A zPDFgIrKPGsGoqc7Y6gHt(!} zFua2swO9==cO;We@EwQ{(6Ujs#6`@B6P}v4Ia;ayH7I9i>vbd1;=8b>;)lgT<&&IK zKoH5ydfA#54*D=#d_a4|GAs*VdD?dZ^q zX3t>1%9KHSj6iyeetMr3y9=}<*-J8ZLx;{T^39<E^PPk43?YP! z3`8G95%{o%glxp1{n`$tcTR{zLMOhax53nZp6LsXeo@fL$|JD%6glkTg-E~AN#1$W zK}i%!t_$9&)exUr^R%=n22xMi^D2ulq+rW#`F=cZa_(iCxK^GsIyoRUOKYJxkEcVA z=iI$Vm+hW^dg1PZPpPBUz#|nY=B~9iL@S=n0n@ru*`0ijF_;9KKK(nskld?KSyUz` zaq3M|=*M?Eq#`1<#quEyT#;BF$>UoQdJGsN!ny9qhR-fjTq1cf&Suq8h!EAyL#dcg zfSh;xAvEf;#crjtmY*su+2thmsB94@{|_9Gi)G~(R|!idk0$18I*er}RB zpT5_?jxoX_h`zTuFRD% zP2(^kL|+<=vS2FzWP5s8TucsXV@4_)9FRGwr^escDH_{zGkWr9*whS5*avn?>9-U7IwA;_ zl_~^o?AQ4@I7iD$LCT}MsXjNam6O#01ng#LCz0=*k%;T8iJmbR-IeW9zngOxCS?Z% z1pd&Jdb`1zth=r~roz)|@WbsJuo~SzDDj53vn+N4#~l<}Fho0qVj;4O6$3n}``*1z zCK#7lf+(3vC$R9$gOBG_{}sMX~QZ?{-wmh>a8N?|3fF`LIIsM1YE(|0e=D zKE^CUh@e4ql?Dw%;hV@#W*a%X^cyD80K&~JHWx9(O@N}#uq?~%6>DsKo!6zU%WPp+ z&^wwaRZ;}Pxn0hk8hioN*@{r!TBXGjcJ0O|*h&S5%ruVAUVTyeZ3 zwn`71CB4!yQ{CG(Nk#jt(RTAyLdH6dyQHA%gVcAr2)2PQdu_Zz)`?exN>~p#Mg_fC zjmN=>V!1TU15~ZrJFyaH{PzzpG6s$}+4vdcx?uH4Id7IowLD(ug`_zy(M*@NKjHim zZV}KkGqE6TMYWLN1-1gn(@TX`B-gJ-E zLlaz803(1Yq&AH2Gm#>^?~Udl4c|qX8N+D5NQOyDaP?MTBb=0mMBKQY;4l|De@xsxE|Lc9R2AAwl}X(7Jmk9T0EjGfcz+};sZy9hBWTzo99~r z6QPzF_&>tiPMYE(E*9{f4kI^GKb*h5CZ)3Z9(zd>d54D_9KSfZ0n-SXdWON7-~Dp> z{mu3hWyJK4K>Njn{4So;ycM#*u_~c`2H0nvPI(`<3R|vUydxaf9#$5EA;9l(dV zHsDbs9O`(R!^J)f$_!dC6Bx}}|0ZMPQzWO6wj$wLNp#L&`I$J`DWz3A%U4h(3Yx)D z(AbS`^57r_K89Cj6j`ueOJzbDNSFkN&idXEyI*WR%myP^3YC`ZNN94Ak%{ptmjgx_ zJBDW`ToLNr>ugJE@P|}{S^X89eg(AjrcK1tdlR7SN*HgcMgRlSl=fL z8xpm(=frLd{Ai#lG?yM!scv_0>2r7aLYpt+YU?Rq(FpMgN;!S^zBq8P^Ktqzh3?WU zO?WbL*meG+{ANav*|a^Pt*dplTTG{HN$OxtSJjHXvI7?hiX zsUIG0OjM$?dgUFpGV|o7WJZRW*A|2>L^;awu;TF-WqpMtVk@)GY^%bZ%d=39v?Z>mqakiH2jguIg8v;MF-yU%hn<6!S( zkxO8N?#lNiZ7sNUODZ36r}?Sm;cY~yp31<0?E!9$tzJ5n`MepM@!Rr2-1t&)+Xkkc z0Q8v?{141OnU%+Mq0w41ng~2^PZ=vn6(dZ+wjC{EEHvPQTnJ?u<;kTyi++_fv}bS+ zMdynjCI4fPr0w3FQE|{4Sv#STV1Cq(mP|$R$*{9aXroorA}JZ$PWT9^eo2?lL%p_d zOa&qttpurun@sp7vY2F!>lAAE0Fp-!!+RRCkdkj7e@2NBii#o}cXteA@14H9^dsG) zj47_n+Jm^jYGS5&e?g?xV@pavhg|~}(3>NnYh#VEyBgb7CPEJAJqfQSh!W=1!~Z;gYA)+Oh zT1PtJ>0S?zKjM-i*t_>5kc-*w zV=cHlcyTp0uIMM-G=e(^f<{qzS}{FWZ4VDi6B~u?P(RIbIN!9~hIQ*^Ydd91p*)fX z-Yx?bQg_QaQ!b|3QyBIbue0P#0nKK9JF4Of>NS3=<~8e&DH?5PGe=Z$IQI_a8!uJY z+9UP#Q(Y>f)3rH&9cpJ;W;6dH*Xc`OCDr!vp|7X(Zf`LtkbGF@4w*F6u!=*B4zZW4 zUiTu8GQ%M2Ae;Al@ggB#`AfEx)@VeV>bAXB{q^eb%Gw7*zhRs=lAot>J&r25m1UQt z=?14v2YHGo)zhp_>-l|3*7eqvoD7y4J)JNuR_G{Vs!+`wB8mDPZIjanJ_(-n3PLQ( z2*}^M9g4p$5|osdGU}u!LVwbd)}Oz|e8>l?`1o|EY3257J@}qdejK-TMM|E_8tBvC z1XSmEc8inx&dbVbb`8mCC)P>f0|5K;hsI3W;n$J{UnsTFvsOa1wWk9}aPElo-v$LL zN*7Ni<#kVxzBKOe_fkxJOIiH2#GULQ?1Sd)2er9nB+rJ8aaAdNyU<-yb?1KL9NcLl ze1bdPX{~H(;l;2l@_`YlX~NqY^QV@T9rRD_DmHT?HI{M}e^@jX_5M&;a7kAUixO~0 z^qZFQs~U2=SP+<2kfcqL+iFXTyf`=2kI`|tXk;jNwNmUbCk9nsi}!a+6Ze_ffH`(n z4wC1Fb`j+`fv9XziVUnTcN&!qd?}#Rn9D1ZMf-e`*0>yt5sj1k{meWv-jdsspYivW zLm8;}mcXR566y7G$S#KBxX@#V5!_TzB;d4b!?!XZV=*T;K+|) zY9F^)XAq12rUWK9|)j&ud0gj z8h9&d=1yB7cp_g^_mFL9#+JqVzM&Rp+ar5p#_eDdm>cLKl|FNbCsIsDkNNEt*O08x z-2SErG!-nn8iogO>>EZz&X&~7EM*BP%P#;^NP?{|R1MU?C)lL*^@2Rk=>Fe?B>@^f zB=nl^c-8W!$h}V#>PzkIv0K%b$bx)h`+?;i6Q&SUd75ii!E5=JDY=BRsafkiFjndv zQ`-6mj5M7^qTV%~ewyxWlg}g*;ZG1tT4yw9t2u>t=2u?6diXMnvXu8Mx>%n#N$}uC z-LC%qly_O3mWw%tbX85gKA~f|YA8;u3!f%=vYg5^BI*jQo!uh%3ubtu4@Y=HL*di@ zBTKq#1tK?Ef~6mBvr3v~c`9W%wTIiC4fiWcUVz7fekS>e9)D`s!*;n=Q_NQG|(1$WV`FZ;~| zt3*$$P@+tbO?-C(<|DL)Gxqms?v2@21C11?(2;aw+m%AlzmUu(8(^T`4%SOD;z8u* z!1f?BHvFHnTd_6c^bwbf--Kk%`)-xO?3K=l;`6zgYEJbKR3{K##9r~&cDXPj&8RYQzv$xRZU2pxfyl%PY?0;MmO z6mo{%K5NAVaa|zMu_pQIZc+o!%~-gPtHeM8!Igc zNU2fNj{%i8fobJ597kI%L}=ViAIYI0esF>`>)ih&c#|AofZ3rY*@i2bS}wJH{~$UH-ge!kr^zL4#ceqTCoXlndPpp?e7^xpx1gj_)NXzO*KxG`T~`f&7Dn ze)6k>{zv0K*dljHV6K1w&`@$yipVH&rqLy^63j!otHU7kOscx$CaPGGY)3KFz{g<7k`NDcH*S34BO4I`oyDR0u2f0-{; zaGZQzp6M$7f|$xp6Ek+&M8qlH#-3!OM@@k@9fgqcf#M#KtY+p{|KM|?2OABPJYOYW zYF{PrV22IVCg$wfOyAsC;_kr8&XlhMN=$)2HDzuxCS`Z2s60yT(|37*+D6@ootPf6 zUB#{N;=Jt1k)X?I(PTTl)|vByt~Wb1-c34gh<6($i*Mx3n_<-BQJ{5Lf7uKf_d2Om-=u1x4Qw!v z=3@IytA@YR1hlDz(nTC zr`;&J08>l#jXU(}83yCmSZ*j=pLdGnHL{hBuYt%M;hLxm?pK4JQyR#j6esa#UvaMJ z%?Y`VIxA1_Ob~kJ^Lm6r8@J8lo2vU_uYZvZQpKA#9e6`;=A&_Jtamqr=aMKvY7yFO zI>C%x;+HHLY)+rHd=0|VIE<6ZpOf}G(-U&{W1J$mdJZS@p6WIvLQ)PXUjV}rgf7ZevW97P!1)E$r7N?~VrWZjyKJ0nCk z$IN>G00`kQDJgXYDXD)fuELj8-}xts$oGg-^qIVDkYS=T1w@|s2zC<`H>)G^wq#8$?XMko>|NWEiY3R5zQ4uFvjj<2JLJBs{)u{V%Y`*014)AET zrf7T1>TbG|d|{vzLxIq?)Y<2*lzbgDLTS3Dkd8H!_y7*~qw*3fa2!Vb`APgbYst`+ zx)@hHt66awfcm;qKDc&4IO7}TEQGdXpdVuXn`;b5n5dy6%G|ADX29}-p2*{ z(nnRx+{e~jz=Bpx6hqic5KdqZb%OxC?Cl&}1-(RQ|L_XJKmRtf(*plM+-yZ?^;Fb> zQjRWAAearz#sQM?f_ZS!iednTT`VjGHKk?$rhp%b&|15>ISI0}dwP1Zd2+Kkx>&Ju z3J3_Wb8xY9ae?3nkgKwT7sQF3lZ}Jj-k$y6JzU*nJm4gM2lRjSaMgm}G{CM2b#-)i zF^9@{KpouZ{++_Y{Ga|#?k;wJ(y=gShuT5y;ZRq2ubltUrJRC_`aeB>OJD`FclzT6 z7yCbuZZOM#iS-|`{cib_&c6o&cmF5vf1v-7`yVhIrJ^Dz?P%`)J3Iwx5!&DV3tBju z!z={<`pC;+X2t{I1qtwSaDu?RoMs>aZhj6BKbIwkr2v$N$3g)7Z&V5nu5J(qbLej> zI5`^(&cg>aGUw$nHxuCG2U~Jk{u_mw3k+VB5W9bm z>Nl0eZz?WxUZ^<_6vPSU;R1pAEcieWa~?3r0xH1E3+6L7hw_>Kp|UU+ly!8mhrovu zW)HD~vO76g{b~3uxS)i(f(R`a8^^ya>UIz}OSppwtqQ~(sP^(-Em|;p=u0=qZ#g-6 zx%j#G1h}|4xcRv_c?A9i(t*0T!b|ZtDJKUT*I$bK9v4A)HgIJjzY7&k@W%t5jG&YY z6yoOSqUGplCqnx>Cg5++KlKe1{%cg^VXkn5_wSPbyXap+o&P%e>m0Cy{b>RM|J1D@ z#Qd*LTp=D%i$5K~{r+k)w}v=aLE$I(-xc)_JM8~5TAX}bP%tkq1Y{23;D$@g#{)9s z;KPzft|rtoaw74#S;X8-?)BK!yNZxaFB?=KsCf`QLh z?Ejpw{ub@Gj{grIe-Fn0!ye$&|Lf$x()WLI{ZFp{N`e0h{J-k@pIrZy0{<2Gf7SK> zn_L+Gy5xa6z<&mL!Y^pL(PpUO7ei0Xl;orVzkWY++lrIn7IY_heOCYisrc^=A!yTm z7H&j!Q&5pX-9~%zlpVwM_+}n%Syzyj(6atEmT74B@|to$?ANBPA598_>25azI*dV` zZ^{^1Dl6wo6WpMAKdnHn<~IFGJ_BQmSAwnHpdn9D{$YR~4Tv1i|?A`&7+D4Gak=(_(ClRHC za(}u$@j`w;^#Y8_yq1go(WI+|zKGO{+=|m{w<}B5{E)+LEg4WAEVw-h43Q7_xINx#ayt7Jbn5Ubr0PD#cM_Xz zM8{TI;C0v(4^I=6g&X^_yl${nd&IIjtBtjHC9Y*XM0WbP<=o)jB-o5ED%QVEli{sS zbt5v?q~=M(gMEGmcrh+8b%)4*X3_W9jPmUx>*0KD9hI&XyP}~`zBl{PI924KJC115 z0{)n<#v;zf!CrXwr7C#I?oA(?1)pWHBGIQTyrVd(lzE=_`8DXCa-X;f65E=Dn(<>* zY=H(#PM#OyDuW7(Vo-BXZKslld1J#??ci;-`0ynoAMg6nVZ`3!n0vv!vu71*&T*K< zBms7q=%TDS;@PwzcL>n|DmCKy|XP^Mh|^tV?Y!14EQn#52dB{%=Z$4_BVil|1+SY9#@lr+OZ{yit$m zvs+qZJraZ(SJtOL;kD3_!bp84i0;U;tUHC;|tyU>cH6CVkD!&}OLYEPlg>gwJPDYZ5P z4J}_5xO?NSh5@LUab`0`3ada{dum!zc$D*p`-zPSs7_b4<$J^^qlo>-x);iCi1!VLV1tz@t*^LMw0dsn zd5I>fSS>V%anowELXqvbuD{{cQJai}G6hi|eCVI#1!;zx>6%+B~Z7g zKc${)LFSvHqd@uujTixitXpE>M=&$POet0wgM>lYiUVz)_)rx%Q%8TkKBlJTrkZa_ zu{CG9{`O5(x?K@n9sm;mHWx7#8f4;H43v<;yW&U6nR3_6;#GTu4)(`Xe$f-ASzpPl zkJiX%W0J%}f5LLKi+L_huSeDj(H||;rf(%Dk6~1_->KS5QG^H~R~i;->Q*^egtBjC`ihUty{s)Lx4hSF?NZnEFx~D!1K0-Of}9rFt@sSWP%j zj_AaUK_%0*sp%vp(Vs-nQ#+}Gxl+pk`aUFL{p5!ABu?GvrP$rBg+6n2Sv{A_g*xl) zf@n2h6~#|g1hol<^os)?if0i?BLjOJg-`_$DsqCfCbI@mpIE$yKFetM=}T}!NMmWf fP+Vbi{7Bui$HxV742_3>{{s|cRHdsVO+)?<7X`R9 literal 0 HcmV?d00001 From 7d361955f8fc0716747f266378c73d8e9c2eb861 Mon Sep 17 00:00:00 2001 From: Micah Lee Date: Fri, 6 Aug 2021 13:10:32 -0700 Subject: [PATCH 2/5] Create all the dirs needed when using VM --- dangerzone/container.py | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/dangerzone/container.py b/dangerzone/container.py index f5a636c..8d1fa9d 100644 --- a/dangerzone/container.py +++ b/dangerzone/container.py @@ -88,10 +88,13 @@ def vm_exec(args, vm_info, stdout_callback=None): return exec(args, stdout_callback) -def vm_mkdir(vm_info): +def vm_mkdirs(vm_info): guest_path = os.path.join("/home/user/", str(uuid.uuid4())) - vm_exec(["/bin/mkdir", guest_path], vm_info) - return guest_path + input_dir = os.path.join(guest_path, "input") + pixel_dir = os.path.join(guest_path, "pixel") + safe_dir = os.path.join(guest_path, "safe") + vm_exec(["/bin/mkdir", guest_path, input_dir, pixel_dir, safe_dir], vm_info) + return guest_path, input_dir, pixel_dir, safe_dir def vm_rmdir(guest_path, vm_info): @@ -154,13 +157,9 @@ def convert(global_common, input_filename, output_filename, ocr_lang, stdout_cal # Otherwise, create temp dirs if vm_info: ssh_args_str = " ".join(pipes.quote(s) for s in vm_ssh_args(vm_info)) - print("If you want to SSH to the VM: " + ssh_args_str) - - guest_tmpdir = vm_mkdir(vm_info) - input_dir = os.path.join(guest_tmpdir, "input") - pixel_dir = os.path.join(guest_tmpdir, "pixel") - safe_dir = os.path.join(guest_tmpdir, "safe") + print("\nIf you want to SSH to the VM:\n" + ssh_args_str + "\n") + guest_tmpdir, input_dir, pixel_dir, safe_dir = vm_mkdirs(vm_info) guest_input_filename = os.path.join(input_dir, "input_file") container_output_filename = os.path.join(safe_dir, "safe-output-compressed.pdf") From b82ffa2cac7947ead18f8aa0f787d627d044295a Mon Sep 17 00:00:00 2001 From: Micah Lee Date: Fri, 6 Aug 2021 13:10:56 -0700 Subject: [PATCH 3/5] Make it so windows remember if waiting has finished --- dangerzone/gui/common.py | 3 +++ dangerzone/gui/main_window.py | 9 +++++++-- dangerzone/gui/vm.py | 2 ++ 3 files changed, 12 insertions(+), 2 deletions(-) diff --git a/dangerzone/gui/common.py b/dangerzone/gui/common.py index f29d8e3..362a2fe 100644 --- a/dangerzone/gui/common.py +++ b/dangerzone/gui/common.py @@ -38,6 +38,9 @@ class GuiCommon(object): # Preload list of PDF viewers on computer self.pdf_viewers = self._find_pdf_viewers() + # Are we done waiting (for VM to start, or container to install) + self.is_waiting_finished = False + def get_window_icon(self): if platform.system() == "Windows": path = self.global_common.get_resource_path("dangerzone.ico") diff --git a/dangerzone/gui/main_window.py b/dangerzone/gui/main_window.py index 9b5f2e0..27a2151 100644 --- a/dangerzone/gui/main_window.py +++ b/dangerzone/gui/main_window.py @@ -54,8 +54,12 @@ class MainWindow(QtWidgets.QMainWindow): self.content_widget.close_window.connect(self.close) # Only use the waiting widget if we have a VM - self.waiting_widget.show() - self.content_widget.hide() + if self.gui_common.is_waiting_finished: + self.waiting_widget.hide() + self.content_widget.show() + else: + self.waiting_widget.show() + self.content_widget.hide() # Layout layout = QtWidgets.QVBoxLayout() @@ -70,6 +74,7 @@ class MainWindow(QtWidgets.QMainWindow): self.show() def waiting_finished(self): + self.gui_common.is_waiting_finished = True self.waiting_widget.hide() self.content_widget.show() diff --git a/dangerzone/gui/vm.py b/dangerzone/gui/vm.py index e69a7ab..6680678 100644 --- a/dangerzone/gui/vm.py +++ b/dangerzone/gui/vm.py @@ -76,6 +76,8 @@ class Vm(QtCore.QObject): self.stop() def start(self): + print("Starting VM\n") + self.state = self.STATE_STARTING self.vm_state_change.emit(self.state) From 173f31ff41ca1fd4a1017190f44b7029cd5a6c20 Mon Sep 17 00:00:00 2001 From: Micah Lee Date: Mon, 9 Aug 2021 12:04:17 -0700 Subject: [PATCH 4/5] Start porting VM to Windows --- BUILD.md | 39 +++++++++++++-- dangerzone/gui/vm.py | 72 +++++++++++++++++----------- dev_scripts/dangerzone-container.bat | 2 - install/vm-builder/windows.sh | 12 +++++ install/windows/get-openssh.py | 65 +++++++++++++++++++++++++ install/windows/make-vm.bat | 11 +++++ 6 files changed, 166 insertions(+), 35 deletions(-) delete mode 100644 dev_scripts/dangerzone-container.bat create mode 100644 install/vm-builder/windows.sh create mode 100644 install/windows/get-openssh.py create mode 100644 install/windows/make-vm.bat diff --git a/BUILD.md b/BUILD.md index b1f7ae6..d8fc97e 100644 --- a/BUILD.md +++ b/BUILD.md @@ -31,7 +31,13 @@ Create a .deb: Install dependencies: ```sh -sudo dnf install -y rpm-build podman python3 python3-setuptools python3-pyside2 python3-appdirs python3-click python3-pyxdg python3-requests python3-colorama +sudo dnf install -y rpm-build podman python3 python3-setuptools python3-pyside2 python3-appdirs python3-click python3-pyxdg python3-requests python3-colorama python3-psutil +``` + +Build the latest container: + +```sh +./install/linux/build-container.py ``` Run from source tree: @@ -62,7 +68,9 @@ If you don't have it already, install poetry (`pip3 install --user poetry`). The poetry install ``` -Make sure [Docker Desktop](https://www.docker.com/products/docker-desktop) and vagrant (`brew install vagrant`) are installed and run this to collect the binaries from Docker Desktop and then build a custom Alpine Linux ISO for Dangerzone, and copy them into the `share` folder: +Make sure [Docker Desktop](https://www.docker.com/products/docker-desktop) and vagrant (`brew install vagrant`) are installed. + +Run this to build a custom Alpine Linux ISO for Dangerzone, and copy it into the `share` folder: ```sh ./install/macos/make-vm.sh @@ -97,8 +105,6 @@ The output is in the `dist` folder. ## Windows -Install [Docker Desktop](https://www.docker.com/products/docker-desktop). - These instructions include adding folders to the path in Windows. To do this, go to Start and type "advanced system settings", and open "View advanced system settings" in the Control Panel. Click Environment Variables. Under "System variables" double-click on Path. From there you can add and remove folders that are available in the PATH. Download Python 3.9.0, 32-bit (x86) from https://www.python.org/downloads/release/python-390/. I downloaded python-3.9.0.exe. When installing it, make sure to check the "Add Python 3.9 to PATH" checkbox on the first page of the installer. @@ -115,6 +121,31 @@ Change to the `dangerzone` folder, and install the poetry dependencies: poetry install ``` +Make sure these are installed: + +- [Docker Desktop](https://www.docker.com/products/docker-desktop) +- [Vagrant](https://www.vagrantup.com/downloads) +- [VirtualBox](https://www.virtualbox.org/wiki/Downloads) +- [Chocolatey](https://chocolatey.org/install) + +Open an administrator PowerShell and run: + +``` +choco install vcbuildtools +``` + +Build OpenSSH: + +``` +powershell.exe -executionpolicy remotesigned -File .\install\windows\make-openssh.ps1 +``` + +Run this to build a custom Alpine Linux ISO for Dangerzone, and copy it (and some binaries from Docker) into the `share` folder: + +``` +.\install\windows\make-vm.bat +``` + After that you can launch dangerzone during development with: ``` diff --git a/dangerzone/gui/vm.py b/dangerzone/gui/vm.py index 6680678..5517527 100644 --- a/dangerzone/gui/vm.py +++ b/dangerzone/gui/vm.py @@ -1,5 +1,4 @@ import os -import sys import subprocess import uuid import pipes @@ -10,6 +9,7 @@ import getpass import json import psutil import time +import platform from PySide2 import QtCore @@ -32,24 +32,8 @@ class Vm(QtCore.QObject): self.sshd_port = None self.sshd_tunnel_port = None - # Processes - self.vpnkit_p = None - self.hyperkit_p = None - self.devnull = open(os.devnull, "w") - - # Relevant paths - self.vpnkit_path = self.global_common.get_resource_path("bin/vpnkit") - self.hyperkit_path = self.global_common.get_resource_path("bin/hyperkit") - self.vm_iso_path = self.global_common.get_resource_path("vm/dangerzone.iso") - self.vm_kernel_path = self.global_common.get_resource_path("vm/kernel") - self.vm_initramfs_path = self.global_common.get_resource_path( - "vm/initramfs.img" - ) - # Folder to hold temporary files related to the VM self.state_dir = tempfile.TemporaryDirectory() - self.vpnkit_sock_path = os.path.join(self.state_dir.name, "vpnkit.eth.sock") - self.hyperkit_pid_path = os.path.join(self.state_dir.name, "hyperkit.pid") self.ssh_host_key_path = os.path.join(self.state_dir.name, "host_ed25519") self.ssh_host_pubkey_path = os.path.join( self.state_dir.name, "host_ed25519.pub" @@ -63,11 +47,33 @@ class Vm(QtCore.QObject): self.vm_info_path = os.path.join(self.state_dir.name, "info.json") self.vm_disk_img_path = os.path.join(self.state_dir.name, "disk.img") - # UDID for VM - self.vm_uuid = str(uuid.uuid4()) - self.vm_cmdline = ( - "earlyprintk=serial console=ttyS0 modules=loop,squashfs,sd-mod" - ) + if platform.system() == "Darwin": + # Processes + self.vpnkit_p = None + self.hyperkit_p = None + self.devnull = open(os.devnull, "w") + + # Relevant paths + self.vpnkit_path = self.global_common.get_resource_path("bin/vpnkit") + self.hyperkit_path = self.global_common.get_resource_path("bin/hyperkit") + self.vm_iso_path = self.global_common.get_resource_path("vm/dangerzone.iso") + self.vm_kernel_path = self.global_common.get_resource_path("vm/kernel") + self.vm_initramfs_path = self.global_common.get_resource_path( + "vm/initramfs.img" + ) + + # Temporary files related to the VM + self.vpnkit_sock_path = os.path.join(self.state_dir.name, "vpnkit.eth.sock") + self.hyperkit_pid_path = os.path.join(self.state_dir.name, "hyperkit.pid") + + # UDID for VM + self.vm_uuid = str(uuid.uuid4()) + self.vm_cmdline = ( + "earlyprintk=serial console=ttyS0 modules=loop,squashfs,sd-mod" + ) + + if platform.system() == "Windows": + pass # Threads self.wait_t = None @@ -78,9 +84,6 @@ class Vm(QtCore.QObject): def start(self): print("Starting VM\n") - self.state = self.STATE_STARTING - self.vm_state_change.emit(self.state) - # Delete keys if they already exist for filename in [ self.ssh_host_key_path, @@ -91,6 +94,10 @@ class Vm(QtCore.QObject): if os.path.exists(filename): os.remove(filename) + # Find an open port + self.sshd_port = self.find_open_port() + self.sshd_tunnel_port = self.find_open_port() + # Generate new keys subprocess.run( [ @@ -127,10 +134,6 @@ class Vm(QtCore.QObject): with open(self.ssh_client_pubkey_path) as f: ssh_client_pubkey = f.read() - # Find an open port - self.sshd_port = self.find_open_port() - self.sshd_tunnel_port = self.find_open_port() - # Start an sshd service on this port args = [ "/usr/sbin/sshd", @@ -162,6 +165,13 @@ class Vm(QtCore.QObject): print("> " + args_str) subprocess.run(args, stdout=self.devnull, stderr=self.devnull) + if platform.system() == "Darwin": + self.start_macos() + + def start_macos(self): + self.state = self.STATE_STARTING + self.vm_state_change.emit(self.state) + # Create a JSON object to pass into the VM # This is a 512kb file that starts with a JSON object, followed by null bytes guest_vm_info = { @@ -257,6 +267,10 @@ class Vm(QtCore.QObject): self.vm_state_change.emit(self.state) def stop(self): + if platform.system() == "Darwin": + self.stop_macos() + + def stop_macos(self): # Kill existing processes self.kill_sshd() if self.vpnkit_p is not None: diff --git a/dev_scripts/dangerzone-container.bat b/dev_scripts/dangerzone-container.bat deleted file mode 100644 index 07b3fc3..0000000 --- a/dev_scripts/dangerzone-container.bat +++ /dev/null @@ -1,2 +0,0 @@ -set DANGERZONE_MODE=container -poetry run python .\dev_scripts\dangerzone %* \ No newline at end of file diff --git a/install/vm-builder/windows.sh b/install/vm-builder/windows.sh new file mode 100644 index 0000000..1bfaa1d --- /dev/null +++ b/install/vm-builder/windows.sh @@ -0,0 +1,12 @@ +#!/bin/sh + +VAGRANT_FILES=$(find /vagrant -type f | grep -v /vagrant/.vagrant | grep -v /vagrant/vm) +DANGERZONE_CONVERTER_FILES=$(find /opt/dangerzone-converter -type f) + +for FILE in $VAGRANT_FILES; do dos2unix $FILE; done +for FILE in $DANGERZONE_CONVERTER_FILES; do dos2unix $FILE; done + +/vagrant/build-iso.sh + +for FILE in $VAGRANT_FILES; do unix2dos $FILE; done +for FILE in $DANGERZONE_CONVERTER_FILES; do unix2dos $FILE; done diff --git a/install/windows/get-openssh.py b/install/windows/get-openssh.py new file mode 100644 index 0000000..ce24f1c --- /dev/null +++ b/install/windows/get-openssh.py @@ -0,0 +1,65 @@ +import os +import sys +import inspect +import requests +import hashlib +import zipfile +import shutil + + +def main(): + zip_url = "https://github.com/PowerShell/Win32-OpenSSH/releases/download/V8.6.0.0p1-Beta/OpenSSH-Win32.zip" + expected_zip_sha256 = ( + "0221324212413a6caf260f95e308d22f8c141fc37727b622a6ad50998c46d226" + ) + + # Figure out the paths + root_path = os.path.dirname( + os.path.dirname( + os.path.dirname(os.path.abspath(inspect.getfile(inspect.currentframe()))) + ) + ) + zip_path = os.path.join(root_path, "build", "OpenSSH-Win32.zip") + extracted_path = os.path.join(root_path, "build", "OpenSSH-Win32") + bin_path = os.path.join(root_path, "share", "bin") + + os.makedirs(os.path.join(root_path, "build"), exist_ok=True) + os.makedirs(os.path.join(bin_path), exist_ok=True) + + # Make sure openssh is downloaded + if not os.path.exists(zip_path): + print(f"Downloading {zip_url}") + r = requests.get(zip_url) + open(zip_path, "wb").write(r.content) + zip_sha256 = hashlib.sha256(r.content).hexdigest() + else: + zip_data = open(zip_path, "rb").read() + zip_sha256 = hashlib.sha256(zip_data).hexdigest() + + # Compare the hash + if zip_sha256 != expected_zip_sha256: + print("ERROR! The sha256 doesn't match:") + print("expected: {}".format(expected_zip_sha256)) + print(" actual: {}".format(zip_sha256)) + sys.exit(-1) + + # Extract the zip + with zipfile.ZipFile(zip_path, "r") as z: + z.extractall(os.path.join(root_path, "build")) + + # Copy binaries to share + shutil.copy(os.path.join(extracted_path, "libcrypto.dll"), bin_path) + shutil.copy(os.path.join(extracted_path, "moduli"), bin_path) + shutil.copy(os.path.join(extracted_path, "scp.exe"), bin_path) + shutil.copy(os.path.join(extracted_path, "ssh-agent.exe"), bin_path) + shutil.copy(os.path.join(extracted_path, "ssh-keygen.exe"), bin_path) + shutil.copy(os.path.join(extracted_path, "ssh.exe"), bin_path) + shutil.copy(os.path.join(extracted_path, "sshd.exe"), bin_path) + shutil.copyfile( + os.path.join(extracted_path, "LICENSE.txt"), + os.path.join(bin_path, "LICENSE-OpenSSH.txt"), + ) + + +if __name__ == "__main__": + main() diff --git a/install/windows/make-vm.bat b/install/windows/make-vm.bat new file mode 100644 index 0000000..25c9142 --- /dev/null +++ b/install/windows/make-vm.bat @@ -0,0 +1,11 @@ +REM Build ISO +cd install\vm-builder +vagrant up +vagrant ssh -- dos2unix /vagrant/windows.sh +vagrant ssh -- /vagrant/windows.sh +vagrant halt +cd ..\.. + +REM Copy the ISO to resources +if not exists share\vm mkdir share\vm +cp install\vm-builder\vm\* share\vm From 46681bc77179e47ccbb673d26cacc0defab5ab7e Mon Sep 17 00:00:00 2001 From: Micah Lee Date: Mon, 9 Aug 2021 14:05:07 -0700 Subject: [PATCH 5/5] Start making Windows VM work with virtualbox --- BUILD.md | 13 ---- dangerzone/gui/vm.py | 122 ++++++++++++++++++++++++++++++++++-- install/windows/make-vm.bat | 4 +- 3 files changed, 118 insertions(+), 21 deletions(-) diff --git a/BUILD.md b/BUILD.md index d8fc97e..ce7d99d 100644 --- a/BUILD.md +++ b/BUILD.md @@ -126,19 +126,6 @@ Make sure these are installed: - [Docker Desktop](https://www.docker.com/products/docker-desktop) - [Vagrant](https://www.vagrantup.com/downloads) - [VirtualBox](https://www.virtualbox.org/wiki/Downloads) -- [Chocolatey](https://chocolatey.org/install) - -Open an administrator PowerShell and run: - -``` -choco install vcbuildtools -``` - -Build OpenSSH: - -``` -powershell.exe -executionpolicy remotesigned -File .\install\windows\make-openssh.ps1 -``` Run this to build a custom Alpine Linux ISO for Dangerzone, and copy it (and some binaries from Docker) into the `share` folder: diff --git a/dangerzone/gui/vm.py b/dangerzone/gui/vm.py index 5517527..17b412a 100644 --- a/dangerzone/gui/vm.py +++ b/dangerzone/gui/vm.py @@ -10,6 +10,7 @@ import json import psutil import time import platform +import shutil from PySide2 import QtCore @@ -47,7 +48,12 @@ class Vm(QtCore.QObject): self.vm_info_path = os.path.join(self.state_dir.name, "info.json") self.vm_disk_img_path = os.path.join(self.state_dir.name, "disk.img") + self.vm_iso_path = self.global_common.get_resource_path("vm/dangerzone.iso") + if platform.system() == "Darwin": + self.ssh_keygen_path = shutil.which("ssh-keygen") + self.sshd_path = shutil.which("sshd") + # Processes self.vpnkit_p = None self.hyperkit_p = None @@ -56,7 +62,6 @@ class Vm(QtCore.QObject): # Relevant paths self.vpnkit_path = self.global_common.get_resource_path("bin/vpnkit") self.hyperkit_path = self.global_common.get_resource_path("bin/hyperkit") - self.vm_iso_path = self.global_common.get_resource_path("vm/dangerzone.iso") self.vm_kernel_path = self.global_common.get_resource_path("vm/kernel") self.vm_initramfs_path = self.global_common.get_resource_path( "vm/initramfs.img" @@ -73,7 +78,16 @@ class Vm(QtCore.QObject): ) if platform.system() == "Windows": - pass + self.vboxmanage_path = ( + "C:\\Program Files\\Oracle\\VirtualBox\\VBoxManage.exe" + ) + + self.ssh_keygen_path = os.path.join( + self.global_common.get_resource_path("bin"), "ssh-keygen.exe" + ) + self.sshd_path = os.path.join( + self.global_common.get_resource_path("bin"), "sshd.exe" + ) # Threads self.wait_t = None @@ -101,7 +115,7 @@ class Vm(QtCore.QObject): # Generate new keys subprocess.run( [ - "/usr/bin/ssh-keygen", + self.ssh_keygen_path, "-t", "ed25519", "-C", @@ -116,7 +130,7 @@ class Vm(QtCore.QObject): ) subprocess.run( [ - "/usr/bin/ssh-keygen", + self.ssh_keygen_path, "-t", "ed25519", "-C", @@ -136,7 +150,7 @@ class Vm(QtCore.QObject): # Start an sshd service on this port args = [ - "/usr/sbin/sshd", + self.sshd_path, "-4", "-E", self.sshd_log_path, @@ -168,6 +182,9 @@ class Vm(QtCore.QObject): if platform.system() == "Darwin": self.start_macos() + if platform.system() == "Windows": + self.start_windows() + def start_macos(self): self.state = self.STATE_STARTING self.vm_state_change.emit(self.state) @@ -258,6 +275,84 @@ class Vm(QtCore.QObject): self.wait_t.timeout.connect(self.vm_timeout) self.wait_t.start() + def start_windows(self): + vm_name = "dangezone-podman" + basefolder_path = os.path.join( + self.global_common.appdata_path, "virtualbox-basefolder" + ) + + # See if we already have a VM + exists = False + for line in subprocess.check_output([self.vboxmanage_path, "list", "vms"]): + name = line.split()[0].lstrip('"').rstrip('"') + if name == vm_name: + exists = True + break + + # Create the VM + if not exists: + subprocess.run( + [ + self.vboxmanage_path, + "createvm", + "--name", + vm_name, + "--basefolder", + basefolder_path, + "--ostype", + "Linux_x64", + "--register", + ] + ) + + # Configure the VM + subprocess.run( + [ + self.vboxmanage_path, + "modifyvm", + vm_name, + "--memory", + "4096", + "--nic1", + "nat", + "--cableconnected1", + "on", + ] + ) + subprocess.run( + [ + self.vboxmanage_path, + "storagectl", + vm_name, + "--name", + "DangerzoneBoot", + "--add", + "ide", + "--bootable", + "on", + ] + ) + subprocess.run( + [ + self.vboxmanage_path, + "storageattach", + vm_name, + "--storagectl", + "DangerzoneBoot", + "--port", + "1", + "--device", + "1", + "--type", + "dvddrive", + "--medium", + self.vm_iso_path, + ] + ) + + # Start the VM + subprocess.run([self.vboxmanage_path, "startvm", "--type", "headless"]) + def vm_connected(self): self.state = self.STATE_ON self.vm_state_change.emit(self.state) @@ -267,12 +362,16 @@ class Vm(QtCore.QObject): self.vm_state_change.emit(self.state) def stop(self): + self.kill_sshd() + if platform.system() == "Darwin": self.stop_macos() + if platform.system() == "Windows": + self.stop_windows() + def stop_macos(self): # Kill existing processes - self.kill_sshd() if self.vpnkit_p is not None: self.vpnkit_p.terminate() self.vpnkit_p = None @@ -283,6 +382,17 @@ class Vm(QtCore.QObject): # Just to be extra sure self.kill_hyperkit() + def stop_windows(self): + vm_name = "dangezone-podman" + subprocess.run( + [ + self.vboxmanage_path, + "controlvm", + vm_name, + "poweroff", + ] + ) + def find_open_port(self): with socket.socket() as tmpsock: while True: diff --git a/install/windows/make-vm.bat b/install/windows/make-vm.bat index 25c9142..95def86 100644 --- a/install/windows/make-vm.bat +++ b/install/windows/make-vm.bat @@ -7,5 +7,5 @@ vagrant halt cd ..\.. REM Copy the ISO to resources -if not exists share\vm mkdir share\vm -cp install\vm-builder\vm\* share\vm +mkdir share\vm +cp install\vm-builder\vm\dangerzone.iso share\vm