
    6h                       % S SK r S SKrS SKrS SKr S SKrSSKJrJr  S SKrS SKrS SKrS SKrS SKrS SKrS SKrS SKrSSKJr  SSKJr  Sr/ SQrS	S
SSS.r " S S\R8                  5      r\ V s/ s H  o R<                  R?                  5       PM     sn r SSK!J"r"  S SK#J$r$  Sr%/ SQr&SSSSSSSSSS.	r'\(" \)" \'RU                  5       5       VVs/ s H  u  pX!4PM
     snn5      r+\RX                  " 5       r-S r./ SQr/S  r0SUS! jr1S" r2SVS# jr3S$ r4SVS% jr5SWS' jr6S( r7S) r8S* r9SXS, jr:SYS- jr;0 r<\(\=\>4   \?S.'   SWS/ jr@ " S0 S1\A5      rBS2 rCS3 rDS4 rES5 rFSWS6 jrGSWS7 jrHS8 rISZS9 jrJS: rKSWS; jrL/ S<QrMS= rNS> rOS? rPS@ rQSA rRS+S+SBSSS+S+S+S+\R                  SSS&S4SC jrT " SD SE\R                  5      rU\R                  R                  SF5      rXSG\X4rYSHrZSI r[SJ r\SK r]SL r^SM r_SN r`\R                  4SO jraSP rbSQ rcSR rdSS reST rfg! \ a@  r	\R                  " 5       S:X  a   Sr	C	GN\" \	5        \ R                  " S5         Sr	C	GN+Sr	C	ff = fs  sn f s  snnf )[    N   )TempFilecleanup_temp_fileWindows)open_url)MUA)PackageSourceVersionSeverityFileTagsJustificationzFollowup-ForOwnerUserUsertags	ForwardedControlX-Debbugs-Cc)r   r   r   z4Offer simple prompts, bypassing technical questions.zOffer more extensive prompts, including asking about things that a moderately sophisticated user would be expected to know about Debian.zRLike standard, but assumes you know a bit more about Debian, including "incoming".zBypass most handholding measures and preliminary triage routines.  This mode should not be used by people unfamiliar with Debian's policies and operating procedures.)novicestandardadvancedexpertc                   $    \ rS rSrSrSrSrSrSrg)MODEC   r   r          N)	__name__
__module____qualname____firstlineno__NOVICESTANDARDADVANCEDEXPERT__static_attributes__r       1/usr/lib/python3/dist-packages/reportbug/utils.pyr   r   C   s    FHHFr)   r   )debbugs)AVAILABLE_UISaf  Dear Maintainer,

*** Reporter, please consider answering these questions, where appropriate ***

   * What led up to the situation?
   * What exactly did you do (or not do) that was effective (or
     ineffective)?
   * What was the outcome of this action?
   * What outcome did you expect instead?

*** End of the template - remove these template lines ***)/z/usrz
/usr/sharez/varz
/usr/X11R6z/usr/manz/usr/doc/usr/binoldoldoldoldstableoldoldoldstableoldoldstable	oldstablestabletestingznext-testingunstableexperimental)	stretchbusterbullseyebookwormtrixieforkydukesidr6   c                 r   [         R                  R                  U 5      n U R                  S5      n[	        S[        U5      S-   5       H  nSR                  USU 5      nU[        ;   a  M#  [         R                  R                  U5      (       d  MI  [         R                  " U5      n[         R                  R                  U5      u  pV[         R                  R                  [         R                  R                  XT5      5      n[         R                  R                  " U/XS -   6 n[        U5      s  $    U $ )a  
Return the real path of file `filename`

This is similar to ``os.path.realpath()``. The difference is that
symlinks to a small set of basic directories are not resolved and
just kept in the path if present.

This function is a helper function called only by
:func:`search_path_for()`.

Parameters
----------
filename : string
    name of a file, may include relative or absolute path

Returns
-------
str
    the real path of the given file
r-   r   r   r   N)ospathabspathsplitrangelenjoinfhs_directoriesislinkreadlinknormpathrealpath)filenamebitsi	componentresolveddirfilenewpaths           r*   rK   rK   n   s    * wwx(H>>#D1c$i!m$HHT!AY'	'77>>)$${{9-H''--	2KSww''S(CDHggllXJb$9:GG$$ % Or)   )	/usr/sbinr.   z/sbinz/binz/usr/X11R6/binz
/usr/gamesc                    [         R                  R                  U 5      u  pU(       a  [        U 5      $ [         R                  R                  S[         R                  5      R                  S5      n[         H  nX;  d  M
  UR                  U5        M     U HS  n[         R                  R                  X5      n[         R                  R                  U5      (       d  MH  [        U5      s  $    g)an  
Searches for a file in PATH and common application directories

Given the filename of an executable, this function tries to locate
the file in common application directories (/usr/sbin, /usr/bin/,
/sbin, /bin, /usr/X11R6/bin, /usr/games) and in any additional
directories included in PATH.

:func:`realpath()` is called on the result (if found).

This function is a helper function called only by
:func:`find_package_for()`.

Parameters
----------
filename : string
    name of a file, may include relative or absolute path

Returns
-------
str or None
    the real path of the given file; None if the file was not found
PATH:N)r@   rA   rC   rK   environgetdefpathpathdirsappendrF   exists)rL   dfrA   fullnames        r*   search_path_forra      s    0 77=="DA!!::>>&"**-33C8D=KKN  77<<%77>>(##H%%  r)   c                     SnU [         R                  R                  S5      [         R                  R                  S5      U4 H  nU(       d  M    U$    W$ )z
Determine which editor program to use

Parameters
----------
specified_editor : str
    Specified editor for reportbug, to be used in preference
    to other settings.

Returns
-------
str
    Command to invoke for selected editor program.
z/usr/bin/sensible-editorVISUALEDITOR)r@   rX   rY   )specified_editordebian_default_editoreditors      r*   which_editorrh      sR     7#::>>(+::>>(+(* 6M* Mr)   c                 6    [         R                  " SSU 5      n U $ )a  
Escape globbing pattern characters with backslash

This function is a helper function used only by
:func:`query_dpkg_for()`.

Parameters
----------
filename : str
    filename, possibly using a globbing pattern

Returns
-------
str
    escaped filename (pattern)
z
([*?\[\]])z\\\1)resub)rL   s    r*   glob_escaperl      s    " vvmWh7HOr)   c                     [         R                  " U 5      nU(       a@  [        R                  R	                  S5      (       a  [        R
                  " SU-  5      nX14$ Sn[        R
                  " SU-  5      nX14$ )a(  
Search for a file in a debian binary package

This is done by opening a pipe to capture the output of ``dlocate``
or ``dpkg``.

This function is a helper function used only by
:func:`query_dpkg_for()`.

Parameters
----------
searchfile : str
    the file to look for
use_dlocate : bool
    try to search using dlocate (which is fast, but may not be
    available) or always use dpkg (always available, but slow)

Returns
-------
(pipe, bool)
    Tuple with the pipe and a bool, the latter indicating whether
    dlocate was used (True) or not (False)
z/usr/bin/dlocatez$COLUMNS=79 dlocate -S %s 2>/dev/nullFz'COLUMNS=79 dpkg --search %s 2>/dev/null)shlexquoter@   rA   r]   popen)
searchfileuse_dlocateargpipes       r*   search_piperu      sk    0 ++j
!Crww~~&899xx>DE  xxACGHr)   c                     Sn[        U [        5      (       a  SU ;   a  Sn[        R                  " X[        R                  S9R
                  R                  SS9$ )a  
Capture the output of a program

Since reportbug needs to be able to run in misconfigured locales, we
need to specify an error handler whenever some external input is
processed.  This wrapper function avoids having to specify this
separately for each program invocation.

Parameters
----------
cmd : str or tuple
    The command to execute including any options and arguments

Returns
-------
str
    The output (stdout) of the command
F T)shellstdoutbackslashreplaceerrors)
isinstancestr
subprocessrunPIPEry   decode)cmd	use_shells     r*   get_command_outputr     sK    & I#ss
	>>#zGNNUU]oUppr)   c                 `    [         R                  " 5       n[	        U 5      n[        X15      u  pE0 nU Hx  nUR                  5       nSU;   a  M  UR                  SS5      u  pU	R                  5       n	UR                  S5      n
U
 H"  nX;   a  Xh   R                  U	5        M  U	/Xh'   M$     Mz     UR                  5         U(       d  U(       a  [        U SS9u  p&U(       d&  U R                  S5      (       a  U S	S
 n [        U 5      $ X4$ ! [         a    [         R                  " S5         GNf = f)a.  
Search for a file in a debian binary package

This is done using ``dlocate`` or ``dpkg``.

This function is a helper function used only by
:func:`find_package_for()`.

Parameters
----------
filename : str
    the file to look for
use_dlocate : bool
    try to search using dlocate (which is fast, but may not be
    available) or always use dpkg (always available, but slow)

Returns
-------
(str, dict)
    Tuple with the original filename input parameter and a
    dictionary with matching packages as keys and lists of
    corresponding files as values.
r-   zdiversion by: r   , F)rr   )r.   /usr/librT      N)r@   getcwdOSErrorchdirrl   ru   striprC   r\   closequery_dpkg_for
startswith)rL   rr   _searchfilenamert   dlocate_usedpackageslinepackagerA   packlists              r*   r   r   *  s   0IIK !*N&~CTHzz|T!**T1-zz|==&G"!((.%)F!	    	JJL$X5A ++,QRRAB<h''A  
s   D	 	 D-,D-Fc                 N   0 nU R                  S5      (       a=  [        R                  " S5      nUR                  U 5      nSX$R	                  S5      '   X4$ U S   S:X  a  [        U 5      u  pVU(       a  XV4$ [        U 5      nU(       a  U(       d  U S4$ [        U=(       d    U 5      $ )a2  
Find the package(s) containing this file

Parameters
----------
filename : str
    The name of the file including any path components
pathonly : bool
    If no path component is part of the file name, specify if the
    file should be looked for in the ``PATH`` (directories with
    executables) only or if the entire dpkg database should be
    searched.

Returns
-------
(str, dict)
    Tuple with file name (possibly modified from input parameter
    filename) and a dictionary with matching packages as keys and
    lists of corresponding files as values.
z/var/lib/dpkg/info/z/var/lib/dpkg/info/(.+)\.[^.]+ r   r   r-   N)r   rj   compilematchgroupr   ra   )rL   pathonlyr   	dpkg_infomfnpkglistnewfilenames           r*   find_package_forr   g  s    * H 011JJ@A	OOH%!##{c$X.;!(+K$+122r)   c                    Sn [        USS9nU   U Hq  nUR                  5       R                  S5      S   nU(       d  M.   UR                  S5      u  pEUR                  5       U :X  a  UR                  5       s  sSSS5        $ Ms     SSS5        g! [         a     gf = f! [         a    [        SU-  5           SSS5        gf = f! , (       d  f       g= f)	at  
Lookup email alias of user `username`

Checks if there is an email alias for the user `username` configured
for outgoing mail (in '/etc/email-addresses') and returns that
alias.

This is a helper function for :func:`get_user_id()`.

Parameters
----------
username : str
    the username to look up

Returns
-------
str or None
    an email address (or None if not found)
z/etc/email-addressesrz   r{   N#r   rW   zInvalid entry in %s)openr   r   rC   
ValueErrorprint)usernamerL   fpr   namealiass         r*   find_rewrittenr     s    ( &H(#56 
D::<%%c*1-D"jjo::<8+ ;;=( 
 ,  
    +h67 
 
sF   
B 1C6B!8CC
BB!C9CCC
Cc                 b   SU ;  a  gU R                  S5      S:w  a  gU R                  S5      u  pUR                  S5      (       d  UR                  S5      (       a  gSU;  a  gUR                  S5      (       d  UR                  S5      (       a  gUS;   a  gUR                  S5      (       a  gg)a  
Simple check for email validity

Performs some simple checks on whether the given string looks like
an email address.

Parameters
----------
addr : str
    string to check

Returns
-------
bool
    True if the string looks like an email address, otherwise False
@Fr   .)	localhostzexample.comzexample.netzexample.org)z.examplez.invalidz
.localhostz.testz.example.comz.example.netz.example.orgT)countrC   r   endswith)addr	localpart
domainparts      r*   check_email_addrr     s    " $zz#! JJsOIC  I$6$6s$;$;
*S!!Z%8%8%=%=OO L M Mr)   c                 H    [         R                  R                  U /5      S   $ )a  
Extract email address from a string

Email addresses are often accompanied by a name: ``My Name
<my@domain.org>`` or ``my@address.info (My Name)``. This function
tries to separate the two parts and returns a (name, address) tuple.

Parameters
----------
addr : str
    an email address (possibly including a name component)

Returns
-------
(str, str)
    Tuple containing the name (if found, otherwise empty string) and
    the plain email address
r   )emailutilsgetaddresses)r   s    r*   get_email_addrr     s     & ;;##TH-a00r)   r   c                 *    [        [        X5      5      $ )a  
Get the user's email address and name

If name and email address are not given, try to obtain the missing
info for the current user and return the result.

Parameters
----------
emailaddr : str
    an email address (possibly including a name component)
realname : str
    Real name (will be ignored if the `emailaddr` string contains a name
    component)

Returns
-------
(str, str)
    Tuple containing the name (if found, otherwise empty string) and
    the plain email address
)r   get_user_id)	emailaddrrealnames     r*   	get_emailr     s    * +i:;;r)   c                 V   [         R                  " 5       n[        R                  " U5      n[         R                  R                  SU 5      =(       dE    [         R                  R                  S5      =(       d    [         R                  R                  S5      n U =(       d    [        US   5      =(       d    US   n SU ;  a<   [        SS5       nUR                  5       R                  5       nSSS5        U S-   W-   n S	U ;   d  S
U ;   a  [        U 5      u  pU(       d  [         R                  R                  S5      =(       dE    [         R                  R                  S5      =(       d    [         R                  R                  S5      nU(       d;  US   R                  SS5      S   nUR                  SUS   R!                  5       5      nU(       d  U $ ["        R$                  R'                  X45      $ ! , (       d  f       GN= f! [         a    [        R                  " 5       n GN2f = f)aN  
Find email address of the current user

This is similar to :func:`get_email()`, but returns a single string
instead of a (name, address) tuple.

Parameters
----------
emailaddr : str
    address, if already known, possibly including a name component.
    Note that if the 'REPORTBUGEMAIL' environment variable is set,
    its value will overwrite this parameter.
realname : str
    real name, if already known.
charset : str
    not used

Returns
-------
str
    email address string, including a name component if available
    (RFC2047-encoded if the name contains non-ASCII characters)
REPORTBUGEMAILDEBEMAILEMAILr   r   z/etc/mailnamerN<(DEBFULLNAMEDEBNAMENAMEr   ,r   &)r@   getuidpwdgetpwuidrX   rY   r   r   readliner   r   socketgetfqdnr   rC   replace
capitalizer   r   
formataddr)r   r   charsetuidinfomf
domainnames          r*   r   r     s   0 ))+C<<D 0)< ,JJNN:.,JJNN7+  ?^DG4?QI
)	*os+r[[]002
 ,
 Oj0	 i3)+,Y7JJNN=1 .RZZ^^I5N .zz~~f- 	Aw}}S!,Q/H''T!W-?-?-ABH;;!!8"788- ,+ 	*)J	*s0   H G3-H 3
H=H H H('H(statuscachec                 v   U(       d  U [         ;   a	  [         U    $ [        R                  " S5      n[        R                  " S5      n[        R                  " S5      n[        R                  " S5      n[        R                  " S5      n[        R                  " S5      n[        R                  " S5      n[        R                  " S5      n	[        R                  " S	5      n
[        R                  " S
5      n[        R                  " S5      n[        R                  " S5      n[        R                  " S5      n[        R                  " S5      nS=n=n=n=nnS=n=n=n=n=nn/ n/ n/ n/ n/ nSn Sn!Sn" [        R                  " 5       n#[        R                  " U 5      n$U(       a  U [        ;   a  [        SU$-  5      n%O1Sn%O. [        SU$-  5      R                  5       S   n$[        SU$-  5      n%U%R                  [        R                  5       GH'  n&U&R                  5       n&U&(       d  M  U!(       a  U&S   S:X  a  UR                  U&5        OSn!U (       a&  U&SS S:w  a  Sn OU[        R                   " SU&5      -  nUR#                  U&5      (       a  U&R                  SS5      u  n'nM  U
R#                  U&5      (       a  U&R                  SS5      u  n'nM  UR#                  U&5      (       a  U&R                  SS5      u  n'nM  UR#                  U&5      (       a  U&R                  SS5      u  n'nGM#  UR#                  U&5      (       a  U&R                  SS5      u  n'nGMQ  UR#                  U&5      (       a  U&R                  SS5      u  n'nGM  UR#                  U&5      (       a!  U(       d  U&R                  SS5      u  n'nSn!GM  UR#                  U&5      (       a}  U&R                  SS5      u  n'n(U(R                  S5       V)V*s/ s H6  n)U)R                  S5       V*s/ s H  n*U*R                  5       S   PM     sn*PM8     n(n)n*UR%                  U(5        GMI  UR#                  U&5      (       a}  U&R                  SS5      u  n'n(U(R                  S5       V)V*s/ s H6  n)U)R                  S5       V*s/ s H  n*U*R                  5       S   PM     sn*PM8     n(n)n*UR%                  U(5        GM  UR#                  U&5      (       a}  U&R                  SS5      u  n'n(U(R                  S5       V)V*s/ s H6  n)U)R                  S5       V*s/ s H  n*U*R                  5       S   PM     sn*PM8     n(n)n*UR%                  U(5        GMo  UR#                  U&5      (       a  Sn GM  U	R#                  U&5      (       a  U&R                  SS5      u  n'nGM  UR#                  U&5      (       a+  U&R                  SS5      u  n'nUR                  5       S   nGM  UR#                  U&5      (       d  GM  U&R                  SS5      u  n'nGM*     Sn+U(       a  UR                  5       S   n"U"S ;  n+Sn,U(       a  [&        R(                  " U5      n,O~U(       au  U[&        R*                  ;   aP  [&        R*                  U   S!   n[&        R*                  U   R-                  S"S#5      [&        R*                  U   S$   4n,OUR/                  5       nOSnUU[1        U5      [1        U5      [1        U5      UU+UUU,UUU[        R                  R3                  U5      U"[1        U5      U4n-U(       d	  U-[         U '   U-$ ! [
         a    [        R                  " S5         GNf = f! [         a     GNf = fs  sn*f s  sn*n)f s  sn*f s  sn*n)f s  sn*f s  sn*n)f )%a-  
Get information on a binary package, including status

Parameters
----------
package : str
    the name of the package
avail : bool
    if True, also look up the detailed package information if the
    package is not installed (with apt rather than dpkg)

Returns
-------
(..., ...)
    A tuple with 17 components. The components are:

    0.  package version string or None
    1.  available package name or None
    2.  dependencies as a tuple containing lists, each list
        representing alternative dependencies
    3.  recommended packages as a tuple containing lists, each list
        representing alternative recommends
    4.  conffiles as a tuple containing (filename_str, md5sum_str,
        flag_str) tuples
    5.  maintainer name and email address string
    6.  bool indicating whether the package is installed
    7.  origin (content of "Origin:" package header if available)
    8.  vendor of the package if available
    9.  reportinfo
    10. priority string
    11. package short description string (summary)
    12. source name if a source header is available
    13. full package description string (without summary line)
    14. package state string
    15. suggested packages as a tuple containing lists, each list
        representing alternative suggests
    16. archive section of the package
z	Version: z	Package: z
Priority: z(Pre-)?Depends: zRecommends: z
Suggests: z
Conffiles:zMaintainer: zStatus: zOrigin: zBugs: zDescription(?:-[a-zA-Z]+)?: zSource: z	Section: NFr   r-   z,LC_ALL=C.UTF-8 apt-cache show %s 2>/dev/nullz4dpkg-query -W -f='${binary:Package}
' %s 2>/dev/nullr   z'COLUMNS=79 dpkg --status %s 2>/dev/nullrw   r   z /z( (.+) ([0-9a-f]+|newconffile)(?: (.+))?$r   r   Tr   |)config-filesznot-installedr   typer+   btsroot)r   rj   r   r@   r   r   r   rn   ro   
_apt_cacher   rC   
IndexErrorlineseprstripr\   findallr   extendr+   parse_bts_urlSYSTEMSrY   r   tuplerF   ).r   avail	versionre	packagere
priorityre	dependsrerecsre
suggestsreconffilesremaintrestatusreoriginrebugsredescresrcre	sectionre
pkgversionpkgavail
maintainerstatusoriginbugsvendorprioritydescsrc_namesection	conffilesfulldescdepends
recommendssuggestsconfmodedescmodestater   packargoutputr   crudthisdependsxy	installed
reportinfor   s.                                                 r*   get_package_statusr  J  s   N W+7##

;'I

;'IL)J

-.IZZ'FL)J**\*Kjj(Gzz*%Hzz*%HZZ!FZZ67FJJz"E

;'I;??J??J?&;??D?6?H?t?hIHGJHHHEIIK kk'"G j '>HJF F	(G'QSSXSXSZ[\^G $5?A RZZ({{}Aw#~% BQx4  RZZ(SUYZZ	??4  !%D!!4T:^^D!!!ZZa0NT6d###zz$2T8__T""#zz$2T8^^D!!!ZZa0NT6\\$::dA.LT4\\$::dA.LT4H__T"""&**T1"5T; &1%6%6t%<?%<q 34''#,?,QAGGIaL,?%<  ?NN;'\\$"&**T1"5T; &1%6%6t%<?%<q 34''#,?,QAGGIaL,?%<  ?k*d##"&**T1"5T; &1%6%6t%<?%<q 34''#,?,QAGGIaL,?%<  ?OOK(t$$H]]4  #zz$2D*[[!ZZa0ND(~~'*H__T"" JJtQ/MD'w )z Iq!"CC	J**40
	W__$__V,V4F!//&155fiH!//&1)<>J &&(F%.%
2C)	66:x(BJJOOH5ueHo	D #GKc  
*  		R @ ? @ ? @ ?sl   6]" ^	 ^^<^^*2^%^*,^5^0"^5" ^^	
^^^%^*0^5c                   4    \ rS rSrSrS	S jrS rS rS rSr	g)
AvailDBi  z
Split a pipe or file into chunks separated by empty lines

This turns a pipe or file into an iterator that returns chunk by
chunk on each next() call.
Nc                 ^    X l         U(       a  Xl        g U(       a  UR                  U l        g g N)popenobr   ry   )selfr   r  s      r*   __init__AvailDB.__init__  s"    GnnDG r)   c                     U $ r  r   )r  s    r*   __iter__AvailDB.__iter__  s    r)   c                     Sn U R                   (       a  U R                   R                  (       a  O:U R                  R                  5       nU(       d  OUS:X  a  U$ U[	        U5      -  nMg  U(       a  U$ [
        e)Nr   
)r  
returncoder   r   r~   StopIteration)r  chunkr   s      r*   __next__AvailDB.__next__  sh    ||<<**77##%Dt|SYE  Lr)   c                 6   U R                   (       a\   U R                   R                  (       a  O%U R                  R                  S5      nU(       d  OMA  U R                   R	                  5         U R                  (       a  U R                  R                  5         g g )Ni   )r  r$  r   readwaitr   )r  stuffs     r*   __del__AvailDB.__del__-  sd    <<<<**U+  LL77GGMMO r)   )r   r  )NN)
r    r!   r"   r#   __doc__r  r   r'  r-  r(   r   r)   r*   r  r    s    %(r)   r  c                  ^    [         R                  " SS[         R                  SS9n [        U S9$ )z
Get the dpkg status database as an :class:`AvailDB` object.

This is a helper function for :func:`get_package_info()`.

Returns
-------
AvailDB
    A :class:`AvailDB` object to access the dpkg status database
)z
dpkg-queryz--statusrz   T)r|   ry   textr  r   Popenr   r  subps    r*   get_dpkg_databaser7  <  s/     6?QZdZiZiptuD4  r)   c                  \    [         R                  " S[         R                  SS9n [        U S9$ )z
Get the database of available packages as an :class:`AvailDB` object

This function is not used anywhere and might be removed soon.

Returns
-------
AvailDB
    A :class:`AvailDB` object to access apt's available database
)z	apt-cache	dumpavailT)ry   r1  r2  r3  r5  s    r*   get_avail_databaser:  K  s)     6zUYZD4  r)   c                 ^    [         U    R                  S   R                  $ ! [         a     Of = f [        R
                  R                  5       nUR                  U 5      (       a  UR                  $  g! [        R
                  R                   a  n[        SU S35         SnAgSnAff = f)z
Get the source package name of a given package

Parameters
----------
package : str
    the name of a (source or binary) package

Returns
-------
str or None
    the name of the corresponding source package
r    Cannot look up source package: ''N)r   versionssource_nameKeyErroraptapt_pkgSourceRecordslookupr   Errorr   )r   
srcrecordses      r*   get_source_namerH  [  s    '"++A.::: 7[[..0
W%%%%% &  ;; 7015667s#   " 
//?A5 5B,B''B,c                    / n [         R                  R                  5       nUR                  U 5      (       aC  UR                  U :X  a  UR                  UR                  5        UR                  U 5      (       a  MC  [        [        U5      5      S:X  a  US   $ g! [         R                  R                   a  n[        SU S35         SnANPSnAff = f)z
Get the package version of a given source package

Parameters
----------
package : str
    the name of a source package

Returns
-------
str or None
    the version of the source package
r<  r=  Nr   r   )rA  rB  rC  rD  r   r\   versionrE  r   rE   set)srcnamer>  rF  rG  s       r*   get_source_versionrM  w  s     H7[[..0
((!!W,
 2 23 (( 3x=Q{ ;; 7015667s   A5B C7CCc                    / n[        5       n [        R                  R                  5       nUR                  U 5      (       a  UR                  U;   a  M(  U(       a  UR                  U :w  a  MA  UR                  UR                  5        [        UR                  5       H4  n [        U   R                  S   R                  nU(       d  M-  X&U4/-  nM6     USUR                  -   S4/-  nUR                  U 5      (       a  M  U$ ! [        R                  R                   a  n[        SU S35        Us SnA$ SnAff = f! [         a     M  f = f)a  
Get list of binary packages belonging to a (source) package.

Parameters
----------
package : str
    the name of a (source or binary) package
only_source : bool
    should be set to True if only source package names should be
    matched (like apt-cache showsrc --only-source)

Returns
-------
[(str, str), ...]
    A list of (name, short description) tuples describing the binary
    packages belonging to the source package of the given package
r<  r=  Nr   zsrc:zSource package)rK  rA  rB  rC  rE  r   rD  r   addsortedbinariesr   r>  summaryr@  )r   only_sourcer   foundrF  rG  bpr  s           r*   get_source_packagerV    s9   $ HEE[[..0

 

G
$
$&:--8		*$$%,,-B!"~..q199 t$ZL( . 	fz1113CDEE# 

G
$
$& O/ ;; 0156   s/   D ! E D="D82D=8D= 
EEc                    U (       d  / $ [        5       nSn0 n/ n/ nU  H3  u  pxXtU'   [        R                  " U5      n	UR                  U	S-   5        M5     SSR	                  U5      -   S-   SU-   S-   SR	                  U5      -   S-   U-   S	-   /n[        UR                  5       5      n
0 nU Vs/ s H(  n[        R                  " U[        R                  5      PM*     nn[        R                  " S
[        R                  5      n[        R                  " S[        R                  5      n[        R                  " S[        R                  5      n[        R                  " S[        R                  5      n/ nU GHd  nU GHY  nUR                  U5      nU(       d  M  UR                  U5      R                  S5      nUR                  U5      R                  S5      nUR                  5       nUS   S   US   S   -   nUS   S;  d	  US   S:X  a  M  UR                  S5      S:X  a#  UR                  S5      R                  5       S   nOSnUR                  U5      R                  S5      nUR                  U5      R                  S5      nUUUUU4nUR                  U5        UR                  U5      nU(       a  U H  nSUU'   M
     UU;  d  GMT  SUU'   GM\     GMg     U(       a  U$ U
 Hb  nU Vs/ s H  oU;  d  M
  UPM     nn[        U5      [        U5      :X  d  M6  X{;  d  M=  UR                  SR	                  U5      SSSS45        Md     U$ s  snf s  snf )a6  
Collect information about one or more packages

This is a helper function for :func:`packages_providing()` and
:func:`get_dependency_info()`.

Parameters
----------
packages : [((str, ...), str), ...]
    List of ((pkg1, pkg2, ...), package) tuples about which to look
    up information. Each tuple consists of two elements:

    - another tuple specifying a "group" of package names
      representing alternative dependencies
    - one specific package name that should also be part of the
      group. Virtual package names are allowed.

skip_notfound : bool
    Include information about (group, package) tuples about which no
    information at all was found, indicating just this.

Returns
-------
[(str, str, str, str, str or None), ...]
    List of (name, status, version, shortdescription, provides)
    tuples about each specific package in the input tuples (not
    groups). If multiple packages providing one of the packages are
    found, information on all of these packages is returned and the
    corresponding "provides" field is filled in the output tuples.
z&(?:[\S]+(?:\s+\(=[^()]+\))?(?:$|,\s+))z(?:\s+\(=[^()]+\))?z^(?P<hdr>Package):\s+(r   z)$z^(?P<hdr>Provides):\s+z	*(?P<pkg>z)(?:$|,\s+)z*$z^Package: (?P<pkg>.*)$z^Status: (?P<stat>.*)$z^Version: (?P<vers>.*)$z*^Description(?:-[a-zA-Z]+)?: (?P<desc>.*)$pkgstatr   r   ihr   nhdrProvidesNversr  Tz | pnz<none>z(no description available))r7  rj   escaper\   rF   listvaluesr   	MULTILINEsearchr   rC   rY   rE   )r   skip_notfoundpackinfopkgnamegroupfor
searchpkgs
searchbitsr   r   escpkggroupsrT  r  	searchobspackobstatobversobdescobretpobr   packrY  sinfoprovidesr^  r  r   itemnotfounds                                  r*   get_package_inforz    s   > 	 "H7GHJJ$!7#&#99: % 	"CHHZ$884?!G+l:
((:
	!/	029	:<@	A	J (//#$FE6@AjAr||,jIAZZ0",,?FZZ0",,?FZZ12<<@FZZDbllSF
CB		!Aq}}Q'--e4}}Q'--f5

Qx{U1Xa[0
 7$&$q'S.775>Z/ wwu~335a8H#H}}Q'--f5}}Q'--f5dD$9

4  T* %&*d !&5(&*E(O;  @ 
$7u!Au7x=CJ&!

EJJu-tX8$@ A	  Jc BV 8s   ./M2	M?Mc                 j    [        U 4U 4/SS9n/ nU H  nUR                  US   US   45        M     U$ )aG  
Get a list of packages providing a given package name

Parameters
----------
package : str
    package name to be looked up in 'Package:' and 'Provides:'
    fields

Returns
-------
[(str, str), ...]
    List of (name, shortdescription) tuples for each (non-virtual)
    package providing the given (possibly virtual) package
T)re  r   r   )rz  r\   )r   aretrr  rX  s       r*   packages_providingr}  /  sI      wj'234HD
C

CFCF#$  Jr)   c           
      r   U(       d  SU < SU< S3$ / nU HK  nU Vs/ s H  oUR                  S5      S   PM     nnU H  nUR                  [        U5      U45        M!     MM     SU < SU< S3n0 n[        U5       H1  n	U	S   n
X;  a  XU
'   M  U	S   (       d  M  X   S   (       a  M-  XU
'   M3     [	        UR                  5       5      nUR                  5         / nU H-  u  pnnnU(       a  US	U-   S
-   -  nUR                  XU45        M/     Un[        U Vs/ s H  n[        US   5      PM     sn5      n[        U Vs/ s H  n[        US   5      PM     sn5      n[        U[        SU-
  S5      5      n[        USU-
  5      nSS jnU H  u  pnUU" XUUUS9-  nM     U$ s  snf s  snf s  snf )a  
Provide information on the dependencies of a package

For each of the provided dependencies, the status and version is
collected. The result is formatted as a table and returned as a
single string.

Parameters
----------
package : str
    name of the package to which the dependency list belongs
depends : [(str, ...), (str, ...), ...]
    list of tuples, each tuple giving a "dependency group" of simple
    dependencies or groups of alternative dependencies
rel : str
    should be either "depends on", "recommends", or "suggests" and
    will be printed along with the package name above the dependency
    table

Returns
-------
str
    a table listing the status and versions of dependencies
r#  rw   z no packages.
rW   r   z
Versions of packages z:
r   z []r   I      c                     SR                  XX#US9nXS (       d	  X$S (       aB  XS nX$S nUSR                  XX4S9R                  5       S-   -  nXS (       a  M7  X$S (       a  MB  U$ )z)line-wrap long package names and versionsz{:3.3} {:{wp}.{wp}}  {:.{wv}}
wpwvNz    {:{wp}.{wp}}  {:.{wv}}r#  )formatr   )r   ru  rJ  r  r  r   s         r*   	table_row&get_dependency_info.<locals>.table_row  s}    077gY[7\3i73<9DclG077"7T[[]`dddD 3ii73<< r)   r  )$   %   )
rC   r\   r   rz  ra  rb  sortmaxrE   min)r   r  reldependenciesdepr^   bitdepinfopacksr   rX  deplistdeplist2ru  r   r^  r  rw  r  maxpmaxvwidthpwidthvr  s                           r*   get_dependency_infor  G  s   2 ,3S9:L(+,1wws|A,CsS 12   4;C@GE .1g#J!WW:a==!c
 / 5<<>"GLLNH07,tT8D8Oc))DV,- 18 G 7+7aAaD	7+,D7+7aAaD	7+,Ds29b)*FrF{#F !(V9V4FvFF !( N_ -< ,+s   F*F/F4c                 @   [         R                  R                  S5      n[         R                  R                  5       nUR	                  U 5        UR
                   H@  nX1;   d  M
  X   R                   H$  nUR                  UR                  -  (       d  M#      g   MB     g)a  Check if a source package has any binary packages with Multi-Arch: same

Parameters
----------
src_package : str
    the source package to find binary packages for

Returns
-------
bool
    Indicates whether Multi-Arch: same was found (True) or not (False)
NTF)	rA  rB  CacherC  rD  rQ  version_list
multi_archMULTI_ARCH_SAME)src_packagecachesrcbin_packagerJ  s        r*   has_multiarch_samer    s|     KKd#E
++
#
#
%CJJ{|| -::%%(?(??? ; $
 r)   c                 &   0 n/ nU  H  u  pEn [        USS9 nUR                  5       nSSS5        [	        S[
        R                  " U5      -   5      R                  5       S   n
X:X  a  Md  UR                  U5        SnW H1  nU(       d  M  US	:X  a	  U(       d  M  US   S
:X  a	  U(       d  M-  X-  nM3     XU'   M     X#4$ ! , (       d  f       N= f! [         a    US;   a   M  SX$'    M  [         a  n	US;   a   Sn	A	M  XU'    Sn	A	GM  Sn	A	ff = f)a  
Get information about modified config files

Parameters
----------
conffiles : [(str, str, str), ...]
    List of (filename, md5sum, flag) tuples
nocompress : bool
    determines whether empty lines and comment lines should be
    included in the output

Returns
-------
({str: str, ... }, [str, ...])
    tuple with two components:

    - dictionary of modified config files, with filenames as keys
      and ("compressed" if desired) config file content as values
    - filename list of the modified config files
rz   r{   N)obsoletezremove-on-upgradez[file not found]zmd5sum r   z	changed:
r#  r   )	r   	readlinesFileNotFoundErrorr   r   rn   ro   rC   r\   )r  
nocompressconfinfochangedrL   md5sumflagr   linesmsgfilemd5thisinfor   s                r*   get_changed_config_filesr    s   * HG$- 4	h'9:b ; %YX1F%FGMMOPQRx Dt|JAw#~jH  &A %.D A ;:  	88!3H 	88!$X		sE   
CC C 
C	
CCD$D+	D4D DD)r2   r3   r4   r5   r6   c                     S=n =n=p#/ n[        S5      nU(       a  [        R                  " S[        R                  5      n0 nUR	                  U5       H`  nUR                  SS5      u  pU
[        ;   a   [        U	5      [        R                  U
5      pO[        U	5      [        [        5      pSX{X4'   Mb     U(       aZ  [        UR                  5       5      nUR                  5         UR                  5         U Vs/ s H  oS   US   4PM     nnUS   S   n  [        S	S
S9 nUR                  5       R!                  5       nSSS5        U(       a  USU-   S-   -  nU (       a  USU -   S-   -  nU(       a3  SR+                  U Vs/ s H  n[-        U5      PM     sn5      nUSU-  -  nU(       a  X-  nU$ s  snf ! , (       d  f       N~= f! ["         a    [%        S[&        R(                  S9   Nf = fs  snf )z
Collect information about the distribution and release

Find out which distribution (Debian/Ubuntu/) this is, which release,
and APT preferences and policy.

Returns
-------
str
    text summarizing the collected information
r   zapt-cache policy 2>/dev/nullzE\s+(\d+)\s+.*$\s+release\s.*o=(Ubuntu|Debian|Debian Ports),a=([^,]+),r   r   Tr   r   z/etc/debian_versionrz   r{   Nz"Unable to open /etc/debian_version)rR   zDebian Release: r#  z  APT prefers r   z  APT policy: %s
)r   rj   r   rc  finditerr   	DISTORDERintindexrE   ra  keysr  reverser   r   r   r   r   sysstderrrF   r~   )debversdebinfoverfilewarndistsr  mrerT  r   pworddistnamepridistr  fob	policystrs                   r*   get_debian_release_infor    s    *,+G+g+E >?Fjjacecocop\\&)E#kk!Q/OE9$J	(ATJIT+/E'( * &EJJLMMO+015adAaD\5E1AhqkGE'0BCslln**,G D
 %/$66#g-44 IIu5u!s1vu56	')33N+ 2 DC E2DE 6s<   <F6
G $F;G G4;
G	G 	G "G10G1c                      [        S5      $ )zT
Get LSB release information

Returns
-------
str
    Information about LSB release
zlsb_release -a 2>/dev/null)r   r   r)   r*   lsb_release_infor  '  s     :;;r)   c                  
   [        S5      R                  5       n U (       db  [        R                  " 5       nUS   n [        R
                  " SSU 5      n [        R
                  " SSU 5      n [        R
                  " SSU 5      n U $ )	zk
Get the architecture of the current system.

Returns
-------
str
    architecture name (e.g., ``"i386"``)
z0COLUMNS=79 dpkg --print-architecture 2>/dev/nullr   zi[456]86i386s390xs390ppcpowerpc)r   r   r@   unamerj   rk   )archuns     r*   get_archr  3  sj     PQWWYDXXZ!uvvk640vvh-vvfi.Kr)   c                  V    [        S5      n SR                  U R                  5       5      $ )z
Check if multiarch is used (foreign architecture(s) defined)

Returns
-------
str
    comma-separated list of foreign architectures
z9COLUMNS=79 dpkg --print-foreign-architectures 2>/dev/nullr   )r   rF   
splitlines)outs    r*   get_multiarchr  F  s%     X
YC99S^^%&&r)   c                  P    [         R                  R                  S5      S:X  a  S$ S$ )z
Check if the system is merged-usr

Returns
-------
str
    Empty if merged-usr, a note that the system is not merged-usr otherwise
z/libr   r   zmerged-usr: no
)r@   rA   rK   r   r)   r*   get_merged_usrr  S  s&     !!&)Z72O=OOr)   debianc                     SSK Jn  U [        R                  ;  =(       a    U=(       a    UR                  (       + nUR                  XUX6XXUXXUXWUUS9n[        U5      $ )a  
Generate a bug report template

Parameters
----------
package : str
    package name
pkgversion: str
    package version
severity : str
    bug severity
justification : str
    reason why critical severity is justified (if applicable)
depinfo : str
    dependency information (like from
    :func:`get_dependency_info():func:`)
confinfo : str
    config file information
foundfile : str, optional
    the name of the file where the bug is
incfiles : str, optional
    files to include in the report
system : str, optional
    most often "debian"
exinfo : int, debianbts.Bugreport or False
    number of the bug for which this message provides extra
    information
type : str, optional
    should be either 'debbugs' or 'launchpad'
klass : str, optional
    unused
subject : str, optional
    could be bug report mail subject
tags : str, optional
    tags to be set for this bug
body : str, optional
    main report message text
mode : int, optional
    reportbug mode (novice, expert, etc.)
pseudos : str, optional
    pseudo-headers to include inline in the report body
debsumsoutput : str, optional
    debsums error output text
issource : bool, optional
    flag whether this report is on a source or binary package

Returns
-------
str
    bug report message template with inline system information
r   )	bugreport)rJ  severityjustificationrL   modesubjecttagsbodypseudoheadersfollowupr   systemr  sysinfor  incfilesdebsumsoutputissource)r   r  r+   debotherbuildd_formatr~   )r   r   r  r  r  r  	foundfiler  r  exinfor   klassr  r  r  r  pseudosr  r  optionsr  r  reps                          r*   generate_blank_reportr  _  sl    t g...ZG4YGDYDY@YG 

gH,9#'t,3f%+g'/,9H  NC s8Or)   c                       \ rS rSrSrS rSrg)our_lexi  z&Quote-removing lexical analyzer objectc                     [         R                   R                  U 5      nUb  [        U5      (       d  U$ US   US   :X  a  US   U R                  ;   a  USS nU$ )z'Get token by token, with quotes removedr   r   )rn   	get_tokenrE   quotes)r  tokens     r*   r  our_lex.get_token  sW    %%d+=E

L!Hb	!uQx4;;'>!BKEr)   r   N)r    r!   r"   r#   r/  r  r(   r   r)   r*   r  r    s
    0r)   r  z~/.reportbugrcz/etc/reportbug.conf)(sendtor  muamtar   r   btsverifyreplyto
http_proxysmtphostrg   debconfr  signnoccr  	dontquerynoconfmirrorskeyidheaders	interfacetemplater  check_available	query_src	printonlyoffline	check_uidsmtptlssmtpuser
smtppasswdparanoidmbox_reader_cmdmax_attachment_sizelistccmeoutfile	draftpathtimeoutc                  R    [         R                  R                  [        5      (       + $ )z
Check if user configuration file exists

Unless reportbug is run for the first time, the user config file
will often exist.

Returns
-------
bool
    True if reportbug is run for the first time
)r@   rA   r]   USERFILEr   r)   r*   	first_runr    s     ww~~h'''r)   c                     0 n [          GHE  n[        R                  R                  U5      (       d  M*   [	        [        USS9SS9nUR                  S-   Ul        UR                  5       nU(       d  Mj  UR                  5       nUS;   a  X0S'   GOUS:X  aO  UR                  5       R                  5       nU[        [        R                  R                  5       5      ;   a  X0S'   GOPUS	:X  a)  U R                  S
/ 5      UR                  5       /-   U S
'   GO!US;   a
  US:H  U S'   GOUS;   a
  US:H  U S'   GOUS;   a
  US:H  U S'   GOUS;   a
  US:H  U S'   GOUS;   a
  US:H  U S'   GOUS;   a  SX'   GOUS;   a  UR                  5       nX@U'   GOUS;   a
  US:H  U S'   GOUS:X  aD  UR                  5       R                  5       nUS;   a  X0S'   GOiUS :X  a  S!U S'   GO\US":X  a  S#U S'   GOOUS$:X  aN  UR                  5       R                  5       nUS%:X  a  S&nU[        [        R                  " 5       5      ;   a  X0S''   GOUS(:X  aE  UR                  5       R                  5       nU[        [         R                  5       5      ;   a  XPU'   GOUS):X  aO  UR                  5       R                  5       nU[        [        R"                  R                  5       5      ;   a  X0S)'   GO[US*:X  a)  U R                  S+/ 5      UR                  5       /-   U S+'   GO,US,;   a
  US-:H  U S.'   GOUS/:X  a  UR                  5       R                  5       nOU[$        ;   a  [$        U   U S0'   OUS1;   a	  US2:H  U S3'   OUS4;   a	  US5:H  U S5'   OUS6;   a	  US7:H  U S7'   OUS8;   a	  US9:H  U S:'   OUS;;   a	  US<:H  U S<'   OUS=:X  a  UR                  5       n['        U5      U S='   OpUS>:X  a  UR                  5       n['        U5      U S>'   OKUS?:X  a#  UR                  5       R                  5       nX0S?'   O"[(        R*                  R-                  S@U-  5        UR                  5       nU(       a  GM  GMH     U $ ! [         a     GMZ  f = f)Az~
Parse the reportbug configuration files

Returns
-------
dict
    dictionary with configuration parameter and their settings
rz   r{   T)posixz-.@/:<>)quiet	maintonlysubmitr  r  headerr  )no-ccccr&  r  )no-compresscompressr(  r  )zno-list-cc-me
list-cc-mer*  r  )no-query-btsz	query-btsr+  r  )r   no-config-filesr,  r  )r  r  r  )r   r   r  r  r  rg   r  r  r  r  r  r
  r  r  r  )z
no-smtptlsr  r  r  )pgpgpggnupgr.  noner   uigtk2gtkr  r  r  mirrorr	  )zno-check-availablecheck-availabler5  r  reportbug_versionr  )query-sourcezno-query-sourcer7  r  )r  z
no-debconfr  )r   z	no-verifyr   )	check-uidzno-check-uidr8  r  )r  zno-paranoidr  r  r  envelopefromzUnrecognized token: %s
)FILESr@   rA   r]   r  r   r   	wordcharsr  lowerra  r+   
SEVERITIESr  rY   r,   MODESr   r   r  r  r  write)argsrL   lexr  r  rs   r   s          r*   parse_config_filesrB    sJ    DE77>>(##d84FGtT  MMI5CMMMOE%<<%*Nj(MMO113EW%7%7%<%<%> ??+0Z(h&&*hhy"&=@Q&QDOo-$)W$4DL99*/=*@D&==(-(=D$;;)..)@D%AA&+/@&@DNBB"&DK J J --/C"%K77',	'9DOf_MMO113E.',V')',V&')Vd]MMO113E %]%7%7%9 ::,1[)f_--///1Cd5::<00&)Ue^MMO113EW__%9%9%; <<&+Uh&&*hhy"&=@Q&QDOGG/48I/ID*+11 --/Ac\"%e*DKAA)..)@D%77',	'9DO55&+x&7DN;;).+)=D%99(-(;D$33--/C25c(D./i'--/C&)#hDOn,MMO113E+0(JJ$$%?%%GHi % @ Ky  s   Q
Q$#Q$c                    S=p/ n/ n[        U SS9 nUR                  5       nSSS5        W H  nUR                  5       nUR                  S5      n[	        U5      S:w  a  M5  US   R                  5       US   pU	S:X  a  U
nMV  U	S	:X  a  U
nM`  U	S
:X  a  X:R                  S5      -  nM{  U	S:X  d  M  XJR                  S5      -  nM     XX44$ ! , (       d  f       N= f)z
Parse a packages bug control file

Parameters
----------
filename : str
    bug control file name

Returns
-------
(str, str, [str, ...] , [str, ...])
    tuple with (submit-as, send-to, report-with, package-status)
    control field values
Nrz   r{   r   r   r   r   z	submit-aszsend-tozreport-withrw   zpackage-status)r   r  r   rC   rE   r<  )rL   submitassubmitto
reportwithsupplementalr   r  r   partsr%  datas              r*   parse_bug_control_filerJ  >  s     HJL	h1	2b 
3zz|

4 u:?Qx~~'q[ Hy H}$**S/)J''JJsO+L   z77% 
3	2s   C
Cc                    / n/ n/ n[         R                  " S[         R                  5      nSnS=pU H<  nUR                  U5      nU(       d  M  UR	                  UR                  5       5        M>     S n[         Vs/ s H
  o" U5      PM     nnU HL  nUR                  U5      nU(       d  M  U" UR                  S5      5      nX;  d  M;  UR	                  U5        MN     U R                  [        R                  5       GH4  nU	(       Ga  U(       d  Sn	M  UR                  U5      nU(       ab  US:X  a  U" UR                  S5      5      U;  d  US:X  a;  UR                  S5      S	   S
:w  a#  UR	                  UR                  5       5        Sn
M  U(       a;  Sn
UR                  5       u  nnUS	   S
:w  a  U" U5      nUR	                  UU45        M  U
(       d4  [        U5      (       a$  US	   S:X  a  US   nUS	   US   S-   U-   4US'   GM  GM  UR                  5       [        :w  d  GM,  UUS-   -  nGM7     US:X  a*  U H   u  nnU(       a  Xk< SU< 3/-  nM  Xk/-  nM"     XU4$ 0 n/ nU HB  u  nnU[        ;   a  UU< SU< 3/-  nM  US:X  a  UU;   a  UU==   SU-   -  ss'   M=  UUU'   MD     U H  nUU;   d  M  Xk< SUU   < 3/-  nM     UR                  U5        XU4$ s  snf )a  
Clean up the bug report message

Cleaning up consists of splitting off the headers and pseudo-headers
from the message body. Two variants are distinguished, determined by
the value of parameter `btstype`:

- In "debbugs"-mode, pseudo-headers are recognized based on an
  internal list of known pseudoheader fields. This list can be
  extended using the `pseudos` parameter. Cleaning up includes
  making sure that only a single instance of non-repeatable
  pseudo-headers is present. If multiple instances are present in
  the input, the last one is used.

- In "gnats"-mode, pseudo-headers start with the character '>'; the
  `pseudos` parameter is ignored.

Headers not recognized as known pseudoheader fields are assumed to
be proper headers.

Parameters
----------
dmessage : str
    raw message. Headers and pseudoheaders found in the message will
    be split off and returned separately.
headers : [str, ...]
    list of header strings. Headers and header content provided here
    are passed to the output.
pseudos : [str, ...]
    list of additional fields to recognize as pseudoheaders. The
    field strings must include a colon; any further content after
    the colon is discarded. Field names must be capitalized.
btstype : str
    should be either "debbugs" or "gnats"

Returns
-------
(str, [(str, str), ...], [str, ...])
    tuple with three components:

    - "cleaned" message string
    - list of (header, content) tuples representing headers
    - list of pseudoheaders
z^([^:]+):\s*(.*)$r   Tc                     SR                  U R                  S5       Vs/ s H  oR                  5       PM     sn5      $ s  snf )N-)rF   rC   r   )aphr  s     r*   normphcleanup_msg.<locals>.normph  s/    xx3@A@AA@s   ?r   Fr+   gnatsr   >rw   r  r#  r   r   r   )rj   r   Ir   r\   rl  PSEUDOHEADERSr   rC   r@   r   rE   r   
NEWBIELINEREPEATABLE_PSEUDOHEADERSr   )dmessager  r  btstype
newheaderscollected_pseudoheadersclean_pseudoheadersheaderremessageparsing
lastpseudor%  mobrO  phaccepted_pseudoheadersr   keyvalue
lastheadercontent	unique_phrepeatable_phs                          r*   cleanup_msgri  e  s   Z J zz.5HGG nnV$3cjjl+ B 4AA=RfRj=A nnR 3		!%B/&--b1  rzz*..&C I-#CIIaL19OO#w.399Q<?c3I!!#**,/"
!
 !ZZ\
Uq6S= +C'..U|<C
OOQ3'^
",Q-A1E1L!M
2 ZZ\Z'td{"GC +F '6OFG#FG(D'EE##x/#	  7 $777 IM2--&':;;M ^#)(;f/ !(If 3 )Y	&8I$J#KK ) }- 333a Bs   >K,c                    [        XU5      nUc  g[        5       u  pV UR                  5        H  nUR                  US-   5        M     UR	                  5         U b:   X-  n [        R                  " U 5      nU(       d   [        R                  " U5        g[        R                  " SU-   5        [        R                  " U5        g! [
         a    U < SU< 3n  Nzf = f! [        R                  " U5        f = f)a  
Download an mbox and open it in a mail user agent.

Runs the command specified by cmd, passing the mbox file
downloaded from url as a parameter. If cmd is None or fails, then
fallback to mail program.

Parameters
----------
cmd : str
    command to open the mbox file with, 'mail -f' if None
url : str
    URL to download the mbox file from
http_proxy : str
    http proxy
timeout : int
    download connection timeout in seconds

Returns
-------
None
Nr#  rw   zmail -f )	r   r   r  r?  r   	TypeErrorr@   r  unlink)	r   urlr  r  mboxfdfnamer   errors	            r*   launch_mbox_readerrr    s    . CW-D|*KROO%DHHTD[! &

?-k IIcNE 			% 			*u$%
		%  -!$e,- 			%s5   >C C !C C CC CC C7c                      [         R                  " 5       n [         R                  " 5       nU S:X  a  SU-   $ U S:X  a  SU-   $ g)z
Get the package of the currently running kernel

Identifying the running kernel is needed to force
assignment for 'kernel' package to a real one.

Returns
-------
str or None
    the name of the kernel package, unless it could not be
    determined
Linuxzlinux-image-zGNU/kFreeBSDzkfreebsd-image-N)platformr  release)r  rv  s     r*   get_running_kernel_pkgrw  #  sG     __F G''	>	! 7**r)   c           
      j   [        5       u  p4UR                  5         U" SU < S[        R                  " U5      < S[        R                  " U5      < 35      nSnSnSnS=n	=p/ n[	        USS9 nUR                  5       nSSS5        W H  nUS:X  a  S	nM  US
:X  a  SnM  US:X  a  S	nM!  US:X  a  SnM+  US:X  a  S	nM5  US:X  a  SnM?  U(       a  X-  n	ML  U(       a  X-  n
MY  U(       a!  UR                  UR                  5       5        M  X-  nM     [        U5        XYXU4$ ! , (       d  f       N= f)aK  
Execute and parse the output of the package bugscript

Package bugscripts generate output that can be split into the
following sections: headers, pseudo-headers, text, and a list of
attachments. All sections are optional.

This function executes a package bugscript and parses the ouput,
identifying the section blocks, if present.

Parameters
----------
handler : str
    name of an executable
bugscript : str
    bugscript filename

Returns
-------
(int, str, str, [str, ...])
    Tuple with 5 components: (returncode, headers, pseudoheaders,
    remaining text, list of attachments)
z	LC_ALL=C rw   Fr   rz   r{   Nz-- BEGIN HEADERS --
Tz-- END HEADERS --
z-- BEGIN PSEUDOHEADERS --
z-- END PSEUDOHEADERS --
z-- BEGIN ATTACHMENTS --
z-- END ATTACHMENTS --
)	r   r   rn   ro   r   r  r\   r   r   )handler	bugscriptrunnerfhrL   rc	isheadersispseudoheadersisattachmentsr  r  r1  attachmentsr   r  r   s                   r*   exec_and_parse_bugscriptr  ;  s/   0 :LBHHJ	wI0F',{{8'<> 
?B IOM%''G'mK	h1	2b 
3**I**I22"O00#O00 M..!M %""4::<0- . hk::7 
3	2s   0D$$
D2c                 b    [         R                  " S5      nUR                  U 5      (       a  S$ S$ )z
Check the package name against Debian Policy

Package names must comply with the policy requirements:
https://www.debian.org/doc/debian-policy/ch-controlfields.html#s-f-source

Returns
-------
bool
    True if the package name is valid.
z^[a-z0-9][a-z0-9+-\.]+$TF)rj   r   r   )rX  pkg_res     r*   check_package_namer  {  s,     ZZ23F<<$$4/%/r)   c                     Sn [         R                  R                  S5      (       a  Sn U $ [        R                  " SSS9(       d  Sn U $ [         R                  R                  S5      (       a  S	n U $ [         R                  R                  S
5      (       a>  Sn  [        SS5       nU SUR                  5       R                  5        3-  n SSS5        U $ [         R                  R                  S5      (       a&  [         R                  R                  S5      (       d  Sn U $ ! , (       d  f       U $ = f! [         a     U $ f = f)z
Determines the init system on the current machine

Returns
-------
str
    the name of the init system, and how it was determined
zunable to detectz/run/systemd/systemz!systemd (via /run/systemd/system)z+. /lib/lsb/init-functions ; init_is_upstartT)rx   zupstart (via init_is_upstart())z/run/runit.stopitzrunit (via /run/runit.stopit)z/run/openrczOpenRC (via /run/openrc)z/proc/1/commr   z	, PID 1: Nz
/sbin/initzsysvinit (via /sbin/init))r@   rA   isdirr   callisfiler   r*  r   	ExceptionrH   )initpfs     r*   get_init_systemr    s    D	ww}}*++2 K __JRVW0 K 
+	,	,. K 
}	%	%)	nc*b)BGGIOO$5#677 + K 
	%	%bggnn\.J.J*K +* K  	 K	s0   D1 $%D	D1 
D.)D1 .D1 1
D?>D?c                  r   Sn [         R                  R                  S5      (       a  [        R                  " SS/5      S:X  a  Sn [         R                  R                  S5      (       a  [        R                  " S/5      S:X  a  U c  Sn OU S-  n [        R
                  " S	/5      R                  S
5      nU SUSS -  -  n [        SS5       nUR                  5       nU H8  nUR                  S5      (       d  M  U SUR                  S5      S   SS -  -  n   O   SSS5        U $ U $ ! , (       d  f       U $ = f)z
Determines the linux security module enabled on the current machine

Returns
-------
str or None
    Description of LSM info; None if there is no LSM enabled on the
    machine or if the state cannot be determined
Nz/usr/bin/aa-enabledz--quietr   zAppArmor: enabledz/usr/sbin/selinuxenabledzSELinux: enabled - z; SELinux: enabled - z/usr/sbin/getenforceasciizMode: %s - r  z/etc/selinux/configr   zSELINUXTYPE=zPolicy name: %s=r   )r@   rA   r]   r   r  check_outputr   r   r  r   rC   )lsminfoenforce_statusr_   r  r   s        r*   get_lsm_infor    s%    G	ww~~+,,OO2I>?1D%	ww~~011zHbGc7dhi7i?+G..G#002H1IJQQRYZ=>#2#666'-KKME??>2204::c?13Ecr3JJJG  . N7N .- Ns   *D':!D''
D6c                  >   / SQn / n[         R                  R                  S5      (       aa  [        S5       n[	        UR                  5       5      nSSS5        [        U 5       H%  u  pEWSU-  -  (       d  M  UR                  U5        M'     U$ ! , (       d  f       ND= f)zD
Determines the kernel taint flags

Returns
-------
list of strings
)TAINT_PROPRIETARY_MODULETAINT_FORCED_MODULETAINT_CPU_OUT_OF_SPECTAINT_FORCED_RMMODTAINT_MACHINE_CHECKTAINT_BAD_PAGE
TAINT_USER	TAINT_DIETAINT_OVERRIDDEN_ACPI_TABLE
TAINT_WARN
TAINT_CRAPTAINT_FIRMWARE_WORKAROUNDTAINT_OOT_MODULETAINT_UNSIGNED_MODULETAINT_SOFTLOCKUPTAINT_LIVEPATCH	TAINT_AUXTAINT_RANDSTRUCT
TAINT_TESTz/proc/sys/kernel/taintedNr   )r@   rA   r]   r   r  r*  	enumerater\   )TAINT_FLAGSflagsr   taintedrN   r  s         r*   get_kernel_taint_flagsr    s    K, E	ww~~011,-"'')nG .
 !-GAA~~T" . L .-s   B
Bc                 ^   [         R                  " S5      nUR                  U5      nU(       d  g [        U    nSUR                  U   R
                   Vs/ s H  oUR                  PM     sn;   a  g SnSR                  U 5      SR                  U 5      4 H)  n[        R                  R                  U5      (       d  M)    O    [        R                  " US5       nUR                  5       nX;  a  [        eUR!                  5        Hc  nUR#                  5       S	:w  a.  UR%                  S
5      (       d  UR%                  S5      (       d    O"SUR'                  5       ;   d  M[    SSS5        g   SSS5        gs  snf ! [         a     GNf = f! , (       d  f       g= f! [         a     gf = f)a  
Determine whether a given package is a security update

Detection of security update versions works most reliably if the
package version under investigation is the currently installed
version.  If this is not the case, the probability of false
negatives increases.

Parameters
----------
pkgname : str
    package name
pkgversion : str
    package version

Returns
-------
bool
    True if there is evidence that this version is a security
    update, otherwise False
z(\+|~)deb(\d+)u(\d+)FzDebian-SecurityTNz%/usr/share/doc/{}/changelog.Debian.gzz/usr/share/doc/{}/changelog.gzrtr   z -- rw   zCVE-20)rj   r   rd  r   r>  originslabelr  r  r@   rA   r]   gzipr   r   r@  r  r   r   upper)	rg  r   regex
secversionrs  oclr_   lns	            r*   is_security_updater    s   8 JJ./Ej)Jw!"J!7!?!?!A!? ./!?!A AA 
B6==gF/66w?A77>>"A
YYr4 AB#kkm99;"$"--*?*?r}}UXGYGYrxxz) ! 
 $ !  A!A   !   	   	sf   %E= E8+E= F BF#F$F -F/F 8E= =
F
F
FF F 
F,+F,r  )T)F)r   r   )r   r   zutf-8)z
depends on)gr  r@   rj   ru  r   	tempfilesr   r   ImportErrorrG  r  r   exitrn   r   email.policyenumr   r   r  rA  urlutilsr   mailerr   rT  rV  r>  IntEnumr   r   r<  MODELISTr   r+   reportbug.uir,   rU  rG   CODENAME2SUITEdictra  itemsSUITE2CODENAMEr  r   rK   r[   ra   rh   rl   ru   r   r   r   r   r   r   r   r   r   r~   r   __annotations__r  objectr  r7  r:  rH  rM  rV  rz  r}  r  r  r  r  r  r  r  r  r  r'   r  r  rA   
expanduserr  r:  CONFIG_ARGSr  rB  rJ  ri  rr  rw  r  r  r  r  r  r  )r   codenamesuites   000r*   <module>r     s  .  	 	 6        
  9 ; I*5B	C4<<  %))DqFFLLND)  &
=
7 2-,)$$(#"02 ^EYEYE[@\]@\_X(@\]^YY[
$N%P4*Bq2:z'3T$N#L1,<089v !#T#u* "w|1f 1h!! 88-`iX0Nb09x K	5p	<&
'	P 8:B!)$T"$2BT[["&dU"&GT	ekk 	 77./	)'(jZ$8NN4b*Z0 9;		 =;@0"<B-`Jy>  I%aV *> ^s)   H	 1#II
	II
*I

I