
    iBW                     T   d dl mZmZ d dlZd dlZd dlZd dlZd dlZddlm	Z	m
Z
mZmZ ddlmZ ddlmZmZmZmZmZ ddlmZmZmZmZmZmZmZmZmZmZm Z m!Z!m"Z"m#Z# erddl$m%Z%  e&ed	      s
 e'ed	d
        e&ed      s
 e'edd        e&ed      s
 e'edd        G d de(      Z)y)    )print_functionunicode_literalsN   )ANYWINPY2TYPE_CHECKINGunicode)gencert)QrCodeqr2pngqr2svgqr2txtqrgen)E_ACCESSE_ADDR_IN_USEE_ADDR_NOT_AVAIL	E_UNREACH	HAVE_IPV6IP6_LLIP6ALL
VF_CAREFULNetdevatomic_moveget_adaptersmin_exsunpacktermsize)SvcHubAF_UNIXiIPPROTO_IPV6)   IP_FREEBIND   c                   f    e Zd ZdZd ZddZd Zd Zd Zd Z	d Z
d	 Zd
 Zd Zd Zd Zd Zd Zy)TcpSrvzk
    tcplistener which forwards clients to Hub
    which then uses the least busy HttpSrv to handle it
    c                 *   || _         |j                  | _        |j                  | _        t        j                  d       d| _        g | _        g | _        g | _        i | _	        d| _
        d| _        d| _        d}i }| j                  j                  D ]  }|dk(  rt        j                  rddg}d}ndg}d}n|g}d}|D ]  }g ||<   	 | j                  j                  D ]8  }d}		 |D ].  }	 | j!                  ||       ||   j#                  |       |	dz  }	0 :  | j                  s!| j                  j,                  st)        d      |r| j                  dd       dt/        dddd      i}t0        rt/        dddd      |d<   | j                  j                  D cg c])  }||D cg c]  }|j3                  d      d    c}vs(|+ }}}|r	 | j5                  | j                  j                        | _	        |j7                  | j                  j9                         D ci c]  \  }}|j3                  d      d   | c}}       |s |D ]  }t/        |ddd      ||<    ni | _	        t;               }| j                  j9                         D ]  \  }}|j=                  t>              sd}| j                  j9                         D ](  \  }}||k(  sd	|v s|j=                  t>              r'd}* |s| j                  j@                  s||jC                  |j3                  d      d           g }tE        |j9                               D ]+  \  }}tE        |      D ]  }|j#                  |d|        - i }i }g }g }i }| j                  jF                  j3                  d      D cg c]  }|j=                  d      s|dd   }}d}
tE        |j9                         d       D ]  \  }}|j=                  t>              r||vr!tE        | j                  j                        D ]  }||jI                  |g       vr)||jI                  dg       vr||jI                  dg       vrA|d|}||vr|j#                  |       d} | j                  jJ                  rn| j                  jL                  s|dk(  rd} d	|v rdj%                  |      n|}!|j#                  |
j%                  | |!||             dtO        |      v }"|"r|n|}#	 |#|   j#                  |       | j                  jF                  s|dv r|}$nd j%                  ||      }$g }%d!|v r|"r|%j#                  d!|$f       d!|v sd"|v r|%j#                  d"|$f       |D ]<  }&|&j=                  d#      s|$j=                  |&dd        s*|%j#                  |&|$f       > |%D ]  \  }'}(	 d||'   |(<      |r|D ]  }
| j                  d|
        | j                  jF                  r| jQ                  |       ntS        d$d%       | j                  jT                  |f| j                  jV                  |ffD ]L  \  })}*|)s	tY        |)d&      5 }+|+j[                  d$j]                  |*      j_                  d'             d d d        N | j                  j                  s| j                  j`                  r| jc                  ||      | _        y y #  |r:d	|v r6d
}
| j                  d|
j%                  ||d   t'                     d       d}Y J|	rY O xY w# t(        $ rb}| j                  j*                  s| j                  j,                  r*d}
| j                  d|
j%                  |||      d       d}n Y d }~d }~ww xY wc c}w c c}}w #  d}
| j                  d|
t'               z   d       i | _	        Y xY wc c}}w c c}w #  |g|#|<   Y xY w#  |(di||'<   Y ?xY w# 1 sw Y   xY w)(Nx   F r   ::0.0.0.0Tr   :z0listen on IPv6 [{}] failed; trying IPv4 {}...
{}tcpsrv   zcould not listen on {}:{}: {})cz/could not listen on any of the given interfaces	127.0.0.1z
local only::1/z'failed to discover server IP addresses
external $z&available @ {}://{}:{}/  ([33m{}[0m)c                     | d   S )Nr    )xs    C/home/ubuntu/myenv/lib/python3.12/site-packages/copyparty/tcpsrv.py<lambda>z!TcpSrv.__init__.<locals>.<lambda>   s
    !A$     )keyz http  https[{}])P   r<   z{}:{}puballzip-
)endwbutf-8)2hubargslogsocketsetdefaulttimeoutstoppingsrvboundseen_epsnetdevsnetlistnsrvqrihas_ipv6p_listenappendformatr   	Exception	ign_ebindign_ebind_allr   r   splitdetect_interfacesupdateitemsset
startswithr   lladdsortedwintitleget	http_only
https_onlyr	   _set_wintitleprintwr_h_epswr_h_aonopenwritejoinencodeqrs_qr),selfrF   padokipipsdualipaportsuccessful_bindstexepsr7   k	nonlocalsvll_okndjust_llip2nd2listening_onportsqr1qr2msgsaccessible_on	title_tab
title_varsdesczsprotohipis_extqrtephitsvartktvfnlsfs,                                               r8   __init__zTcpSrv.__init__1   s   HH	77 	  %
	))++ +	BTz??+CD$+C Dd 3 		 #$ " "" LLd3sGNN40,1,	"+	Z xx		 7 7MNNHHXr" QLA
 q"l;CJ $		W1qRU8VQa8V/VQW	W"#55diikkB JJt||7I7I7KLtq!Q*LM" :A#Aq"j9CF: DL ll((* 
	,FB==(G LL..0 $S9CNN64J#G$ $)),,		"((3-*+
	, 
+ 	:IBu :##r4$89:	: 	%)YY%7%7%=%=c%BXallSVFWaeX
X:syy{? 7	0HB}}V$5tyy{{+ 30r2.BFF4$44BFF9b$99 "D)]*!((,99&&YY))TS[#E+."9fmmB'"AHHUCt<=#wt}4#c%GNN4( yy))9$B D1BJ&6KK,J&%:*=KK,% /C~~e,s12w1GS"I./ # 0FB0,-	"b)0_30	7	0r  &1%& 99y)$B YY.YY/
 	=FB "d^ =qGGTYYr]227;<= =	= 99<<499==hhsC(DG )m"#s
$W $188CQ3RTU V&* (  0 (!  yy**dii.E.E;188Bb+AQG" 	( 9WW">1vx<3!L> Y>%#fCG00)+Q	" = =s   #\8)+[1\8
^+%^& ^+^+*^1 !_ 
)_& _&_+_920`1;\5	,\8/\5	1\84\5	5\88	^#A^^#&^+1)_+_69	`	`	c                 *    | j                  d||       y )Nr,   )rH   )rs   msgr.   s      r8   nlogzTcpSrv.nlog   s    3"r:   c                 <
   dx}}d }d}d|v rat         j                  }|j                  d      }|d   }t        |      dkD  rt	        |d   d      }t        |      dkD  r	 t	        |d         }n{d
|v rN|dd  }
t        j                   t	        |
            }|j                  t         j                  k(  }|j                  }n)d|v rd}t         j                  }nd}t         j                  }|xs$ t        j                   |t         j                        }t        r| j                  j                   r/|j#                  t         j$                  t         j&                  d       |r/|j#                  t         j                  t         j(                  d       |j+                  d        	 |j#                  t         j,                  t         j.                  d       t1        | j                  dd      r/|j#                  t         j2                  t         j4                  d       |r| j6                  j9                  |       y 	 |rI| j                  j:                  r| j<                  j9                  ||f       y |j?                  ||f       nJt        s| j                  j@                  r}tB        jD                  jG                  |      rtC        jH                  |       |j?                  |       |dk7  rtC        jJ                  |d|       |dk7  rtC        jL                  ||       nd|tC        jN                         fz  }tB        jD                  jG                  |      rtC        jH                  |       |j?                  |       |dk7  rtC        jJ                  |d|       |dk7  rtC        jL                  ||       tQ        | jR                  ||tT               |r|jW                         d   n|}||k7  rtY        tZ        d	   d      | j6                  j9                  |       y #  d	d l}	|	j                  |d         j                  }Y QxY w#  Y txY w# tX        t         j\                  f$ r}	 |j_                          n#  Y nxY wd}|j`                  tZ        v r&djc                  ||      }|s5djc                  |      }n#|j`                  td        v rdjc                  |      }|s|sd}| jg                  d|d        |s| j                  j@                  s|dz  }ti        |      d }~ww xY w)NFunix:r+      r      r-   r   fd:)filenoTfreebindz%s.%dr(   z*[1;31mport {} is busy on interface {}[0mz![1;31munix-socket {} is busy[0mz&[1;31minterface {} does not exist[0mzD


  NOTE: this crash may be due to a unix-socket bug; try --rm-sck
r,   z#; maybe this is a bug? try --rm-sck)5rI   r   r\   lenintgrpgetgrnamgr_gidr   IPPROTO_TCPfamilyAF_INET6AF_INETSOCK_STREAMr   rG   	reuseaddr
setsockopt
SOL_SOCKETSO_REUSEADDRTCP_NODELAY
settimeoutr    IPV6_V6ONLYgetattrSOL_IPr"   rL   rW   http_no_tcprN   bindrm_sckospathexistsunlinkchownchmodgetpidr   r   r   getsocknameOSErrorr   errorcloseerrnorX   r   rH   rY   )rs   rv   rz   uds_permuds_gidrM   tcpipvudsr   fdrL   tfsportr}   er|   s                    r8   rV   zTcpSrv._listen   s   7b=..C((3-CRB3x!|s1vq>3x!|:!#a&kG
 b[ABBMMR1E++!3!33C,,CBYC//CC..C=v}}S&*<*<=,,NN6,,f.A.A1ENN6--v/A/A1Et	NN6..0B0BEJ 499j%0NN6==&*<*<a@HHOOC 7	99((MM(("d4"d$TYY--ww~~b)		"HHRL"}R12~X. B		#44Bww~~b)		"HHRL"}R12~X.		2r:>,/COO%a(TEu} mA.33HHOOC M:!ll3q6299G4	R & 			Axx=(FMMdTVWAHHLA--BII"MbAHHXq!,tyy//::A,/	sJ   P /P= 35Q )F)Q $P:=QTQ0/T0Q42B$TTc           	         | j                   D cg c]  }|j                         d d  }}g }g }| j                   D ]  }|j                  t        j                  k(  r*d}t        j                  dd|j                               }d}nd}|j                         d d \  }}|t        k(  rd}	 |j                  | j                  j                         	 |j                  t        j                  t        j                        }	|	s(t        d	j                  |j                                     	 |j%                  ||f       |j%                  |       |j'                         }|r>d|v rdj                  |      n|}dj                  |||t)        j*                               }n%dj                  ||t)        j*                               }| j#                  d|       | j                  j,                  rt/        |       | j0                  j2                  j5                  d|        || _         || _        t9        t;        | j<                  |z               | _        t?        |      | _         | jC                          y c c}w #  d}	Y xY w#  |d
k(  rd|f|v r|j!                          Y g|dk(  rd
|f|v r|j!                          Y d}
| j#                  d|
j                  ||      d        xY w)Nr   Fz	\.[0-9]+$r(   r   Tr)   r   zfailed to listen on {}r*   z

ERROR: could not open listening socket, probably because one of the server ports ({}) is busy on one of the requested interfaces ({}); avoid this issue by specifying a different port (-p 3939) and/or a specific interface to listen on (-i 192.168.56.1)
r,   r+   r>   zlistening @ {}:{}  f{} p{}zlistening @ {}  f{} p{}zhttpsrv.listen)"rL   r   r   rI   r   resubr   listenrG   nc
getsockoptr   SO_ACCEPTCONNrY   rX   r   rH   rW   r   r   r   qrj   rF   brokersayrM   listr`   rN   r   rQ   _distribute_netdevs)rs   r7   all_epsrM   srvsrL   r   rv   rz   ru   r|   fnor   r   s                 r8   runz
TcpSrv.rund  so   04911==?2A&9988 2	7CzzV^^+VVL"coo.?@??,Ra0DV|

499<<((9(96;O;OPB #$<$C$CCOODU$VWW $ LL"d$KK**,C+."9fmmB'"299#tS"))+V/66r3		LHHXs#yy{{c
HHOO 0#6e2	7h 
S!678I	  "w :&B
?d|u'<IIK:9d"3w">IIK X188D"#5q9s5   I3*%J.I8>*J8I?<JK&"K& &K&c                    | j                   j                  j                  d| j                         | j                   j	                          t        | j                  | j                  | j                         | j                   j                          | j                   j                          | j                   j                          y )Nzhttpsrv.set_netdevs)rF   r   r   rO   start_zeroconfr
   rH   rG   restart_sftpdrestart_ftpdrestart_tftpd)rs   s    r8   r   zTcpSrv._distribute_netdevs  sw    14<<@!$))T\\2  r:   c                     d| _         	 | j                  D ]  }|j                           	 | j                  dd       y #  Y xY w)NTr,   zok bye)rK   rL   r   rH   )rs   rL   s     r8   shutdownzTcpSrv.shutdown  sD    	xx 		
 	8$	s	   !> Ac                 |   | j                   s/t        j                  | j                  j                         | j                  | j                  j                        }|s^g }g }|j                         D ]+  \  }}|| j                  vs|j                  d|d|       - | j                  j                         D ]!  \  }}||vs|j                  d|d|       # d}| j                  d|dj                  |      dj                  |      fz  d       || _        | j                          | j                   s.y y )Nz
[32m  added z = z
[33mremoved znetwork change detected:%s%sr,   r(   r-   )rK   timesleeprG   z_chkr]   rS   r_   rO   rW   rH   ro   r   )rs   rO   rc   remr   r   r|   s          r8   netmonzTcpSrv.netmon  s   --JJtyy',,TYY[[9GCC E1DLL(JJaCDE **, E1G#JJaCDE /AHHXqBGGCL"''#,#??C"DL$$&% --r:   c           	         |D cg c]  }|j                  d      r| }}t        d      }i }|D ]  }|j                  D ]  }dt        |j                        v r|j                  d   n|j                  }dj                  ||j                        }t        ||j                  xs d|j                  d      }	|	||<   	 t        j                  |	j                        }
|
rE|
|	j                  k7  r6d}| j                  d|j                  |	j                  |
      d	       |
|	_          t        t        |j!                                     }|| j"                  k(  r| j$                  ri S || _        d
|vr>d|vr:|j!                         D ci c]  \  }}|j'                  d      d   |v s||! }}}	 t)        | j+                               }|j!                         D cg c]  \  }}|j                  |v s| }}}|D cg c]  }|j'                  d      d    }}|s
t-               	 |D ]e  }|r	|d
dg|z   vrd}|dv r|n|g}|D ]G  t1        fd|D        d      sd|   j2                  vs-|   xj2                  d|z   z  c_        I g |S c c}w #  Y ^xY wc c}}w c c}}w c c}w #  | j/                         }|r|gng }Y xY w)N)r   r   Tr+   r   z{}/{}r(   z)netdev idx mismatch; ifaddr={} cpython={}r,   r-   r*   r)   r1   z[32mexternal)r*   r)   c              3   L   K   | ]  }|j                  d z         s|  yw)r1   N)ra   ).0r7   rv   s     r8   	<genexpr>z+TcpSrv.detect_interfaces.<locals>.<genexpr>  s      DQ\\"s(-C1Ds   $$r2   , )ra   r   rw   strrv   rX   network_prefixr   index	nice_namerI   if_nametoindexnameidxrH   rd   r_   rP   rO   r\   r   _extdevs_nixrY   	_defroutenextr   )rs   
listen_ipsr7   nicsr~   nicnipry   sipr   r   r|   rP   r   r   ext_devsext_ipsrtlipr   rw   rv   s                        @r8   r]   zTcpSrv.detect_interfaces  s   !+RA1<<@P3QaR
RD! 	Cww #&#cff+#5cffQi366nnS#*<*<=CaCC //8Csbff}G188BFFC+@!D!$	 fSYY[)*dll"t||IJ&4z+A$'IIKQDAq1773<?j3P1a4QCQ	)D--/0H%(YY[GTQAFFh4FqGGG0781qwws|A8G8k!   		0Cc)T):W)DD%D $55'C5C 0DcDbI*CGLL8GLLD4K/L0		0 
c S  R H8	)!B rdbGsS   JJ>A&J	J"(J"1,J3 J(4J(8J3 ?J.J3 J(J3 3Kc              #     K   t        dd      5 }t        |       |D ]R  }|j                  d      j                         j	                         }|d   dk(  s9t        |d   d      dz  sL|d	    T 	 d d d        y # 1 sw Y   y xY ww)
Nz/proc/net/routerbrE   r   00000000r-      r   r   )rm   r   decodestripr\   r   )rs   r   lnrs       r8   r   zTcpSrv._extdevs_nix  s     #T* 	aG IIg&,,.446Q47?s1Q4}q'8A$J	 	 	s)   BAA<A<)	A<3	B<BBc                    d}t        j                   t         j                  t         j                        }dD ]*  }	 |j                  |df       |j	                         d   } n |j                          |S # t
        t         j                  f$ r{}|j                  t        v r"| j                  ddj                  |             n=|j                  t        vr+| j                  ddj                  |j                               Y d }~d }~ww xY w)Nr(   )z10.254.39.23z172.31.39.23z192.168.39.23z239.254.39.23z169.254.39.23r   r   r,   zeaccess {} (trying next)zroute lookup failed; err {})rI   r   
SOCK_DGRAMconnectr   r   r   r   r   rH   rX   r   r   )rs   retsrv   r}   s        r8   r   zTcpSrv._defroute  s    MM&..&*;*;<
 	WBW		2q'"mmoa(	W& 	
	
 V\\* W88x'HHX'A'H'H'LMXXY.HHX'D'K'KBHH'UV	Ws   &A66D
A1DD
c           
         |j                  dddi      |d<   |j                  d|d         |d<   i }|j                         D ]  \  }}|D ci c]
  }d|vs|d }}t        |      }t        |      D ]1  }|j	                  d      d   }||vs|j                  |       d||<   3 |D 	cg c]  }	|	j                  d      s|	 }
}	t        |      dkD  r|
r|
D ]  }|j                  |        |||<    d	}|}| j                  j                  j	                  d
      D ]  }|j                  d      r^t        t        |j                  |dd  ddi      j                                     }dj                  |d d       }t        |      dkD  r|dz  }|dj                  |      z  } t        dj                  |      t         j"                  d	       t         j"                  j%                          y c c}w c c}	w )NrA   z
Local-Onlyr   r@   r+   r   z127.r-   r(   r3   r4   z(None)r   z, ...z{} z	]0;{}\
)filerC   )rf   r_   r`   rd   r\   rc   ra   r   poprG   re   r   keysro   rX   rj   sysstderrflush)rs   vsvs2r   r~   r   filthaverv   r7   lotitlerU   sepss                 r8   ri   zTcpSrv._set_wintitle  s   FF5<"345	FF5"U),5	hhj 	FAs$'9b3b=BE9D9t9DSk !XXc]1%T>HHRL DH	! ":Q\\&%9!:B:4y1} !BHHRL! CF	  ##))#. 	%A||C F266!AB%(A#?#D#D#FGHIId2Ah't9q=LAU\\!_$E	% 	!((/cjjbI

7 : ;s   	G2G2+G7G7c                    |j                         D ci c]  \  }}|dv s|| }}}|j                         D ci c]  \  }}d|v s||vs|| }}}|j                         D ci c]  \  }}||vs||vs|| }}}|j                  |       |j                  |       d }t        |      t        |      z   }| j                  j                  }	| j                  j
                  rJ|	sH|rF| j                  j                  dz   }
t        d |xs |j                         D              ||
<   |
g|z   }|D ]  }|j                  |	      s|	dk(  r nd} |s|	}|syd|v rd|dn|}| j                  j                  rd}n3| j                  j                  rd	}n| j                  j                  rd	nd}|j                  ||j                  |g             }|rd
nd}||v s|sdndj                  |d         }dj                  |||| j                  j                        }|j!                  d      }t"        rt%        dt'        |      z  |      }| j                  j(                  | j                  j*                  dk(  }|rd| j                  j,                  }| j                  j.                  }t1        |      }| j                  j2                  xs g D ]  }| j5                  ||        |dk(  r6	 t7               \  }}t9        |dz  |      }|j:                  |dz  z   |k\  rdnd}t=        |||      }| j                  j>                  rdj                  ||      S dsd|rdfd}|dkD  rtA        jB                  d||      }|jE                  dd      dz   }rdnd}|rd}|d z   }|j                  |      }tF        r|jE                  dd!      }||z   S c c}}w c c}}w c c}}w #  d}Y xY w)"N)r/   r0   r+   z.localc              3       K   | ]  }|  y w)Nr6   )r   r   s     r8   r   zTcpSrv._qr.<locals>.<genexpr>M  s     ;!A;s   .r(   []r  r<   r?   z:{}r   zhttp{}://{}{}/{}rE      Br   r   r   z{}
{}z[40;48;5;{0}m{1}[47;48;5;{2}mz[0;40m{1}[0;47mz[0;7m{1}[0mc           	      `    j                  dt        | j                  d            z        S )Nr3   r   )rX   r   group)mbgfghalfcs    r8   ansifyzTcpSrv._qr.<locals>.ansify  s'    <<C#aggaj/$92>>r:   u   (█+)rB   z[K
z[Kz [0;38;5;{0};47;48;5;{1}mz [0;30;47mz [0mz
{2}[999G[0m[Jz`
`)$r_   r^   r   rG   qrizmr   r   valuesra   rg   rh   rq   rf   rX   qrlrp   r   r   r   qr_fgqr_bgqrpqrzr   qr_file_qr2filer   minsizer   no_ansir   r   replacer   ) rs   t1t2r   zlit2ct2brv   rw   r1  r   r   r=   r   dportrz   txtbtxtnocolorrt   zoomqrctwthtszrR   r0  ccr|   r-  r.  r/  s                                 @@@r8   rr   z
TcpSrv._qrA  s   &(hhjO72sB:N4Nr3wOO&(hhjP72sC2I"C-r3wPP%'XXZS'"c2S=Rs]b#gSS
		#
		#2hb!iimm99<<99>>H,D;b'8'8':;;BtH&3,C 	B}}S!SCZB	
 B #r	nr99EYY!!E99==CbEr266"b>*"e^5rell586L ''sD$))--Hzz'"4#d)+T2DYY__YY__(Biimmyy}}Dk))##)r 	#BMM#r"	# 19!B"'2&HHsQw.#5q1 Cs#99??3++7-E)E	? !8&"-BZZj)H402,8HB..HHRR 		$'AQww PPSxs9   O O O&O&O&,O,9O,>O,55O2 2O8c           	         d|v sd|v r|j                  dd      \  }}}dx}}n|j                  dd      \  }}}}}t        |      }t        |      }	|j                  d      rP|dvrt        d	      t	        |d
      5 }
|
j                  t        |||	      j                  d             d d d        y |j                  d      r@t	        |d
      5 }
|
j                  t        ||	      j                  d             d d d        y t        |||	| j                  |      | j                  |      |       y # 1 sw Y   y xY w# 1 sw Y   y xY w)Nz.txt:z.svg:r+   r   r(      z.txt)r   r   z'invalid zoom for qr.txt; must be 1 or 2rD   rE   z.svg)rsplitr   endswithrY   rm   rn   r   rp   r   r   _h2i)rs   rI  rE  apzs1zs2r-  r.  rH  rt   r   s              r8   r:  zTcpSrv._qr2file  s8   c>W^::c1-LBSLB#&::c1#5 BS"b3x#h;;v6! IJJb$ @1sD#.55g>?@ @[[ b$ :1sC(//89: : 3c499R=$))B-D@ @: :s   >,D3+D?3D<?Ec                 <    	 t        fddD              S #  Y y xY w)Nc              3   B   K   | ]  }t        ||d z    d        yw)r   r  N)r   )r   rS   hss     r8   r   zTcpSrv._h2i.<locals>.<genexpr>  s"     CARAE]B/Cs   )r   r   rO  )tuple)rs   rX  s    `r8   rR  zTcpSrv._h2i  s#    	CCCC	s    N)r   )__name__
__module____qualname____doc__r   r   rV   r   r   r   r   r]   r   r   ri   rr   r:  rR  r6   r:   r8   r%   r%   +   sW    
@)D#l\<#|!%'*2h2!F\|E(r:   r%   )*
__future__r   r   r   r   rI   r  r   r   r   r   r   r	   certr
   qrkoder   r   r   r   r   utilr   r   r   r   r   r   r   r   r   r   r   r   r   r   svchubr   hasattrsetattrobjectr%   r6   r:   r8   <module>rf     s    7 	 	  
  9 9  9 9   " vy!FIu%v~&FNB'v}%FM2&L
V L
r:   