o
    åvŽfóh  ã                   @   sÖ   d Z ddlZddlZddl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
 ddlmZ ddlmZ ddlmZ ddlmZ ejd dk rRdd	lmZ e d
ZnddlmZ dZG dd„ dƒZG dd„ deƒZdS )z(Store, load, and handle problem reports.é    N)Úencode_base64)ÚMIMEMultipart)ÚMIMEBase)ÚMIMEText)ÚBytesIOÚ3)ÚIterableUserDictT)ÚUserDictFc                   @   sB   e Zd ZdZddd„Zdd„ Zdd„ Zd	d
„ Zdd„ Zdd„ Z	dS )ÚCompressedValuez9Represent a ProblemReport value which is gzip compressed.Nc                 C   s(   d| _ || _d| _|r|  |¡ dS dS )zAInitialize an empty CompressedValue object with an optional name.NF)Ú	gzipvalueÚnameÚlegacy_zlibÚ	set_value)ÚselfÚvaluer   © r   ú0/usr/lib/python3/dist-packages/problem_report.pyÚ__init__"   s   ÿzCompressedValue.__init__c                 C   s4   t ƒ }tj| jd|dd |¡ | ¡ | _d| _dS )zSet uncompressed value.Úwbr   ©ÚmodeÚfileobjÚmtimeFN)r   ÚgzipÚGzipFiler   ÚwriteÚgetvaluer   r   )r   r   Úoutr   r   r   r   /   s   

zCompressedValue.set_valuec                 C   s2   | j sdS | jrt | j ¡S tjt| j ƒd ¡ S )zReturn uncompressed value.N©r   )r   r   ÚzlibÚ
decompressr   r   r   Úread©r   r   r   r   Ú	get_value7   s
   zCompressedValue.get_valuec                 C   sX   | j sJ ‚| jr| t | j ¡¡ dS tjt| j ƒd}	 | d¡}|s&dS | |¡ q)z5Write uncompressed value into given file-like object.Nr   Té   )	r   r   r   r   r    r   r   r   r!   )r   ÚfileÚgzÚblockr   r   r   r   A   s   


üzCompressedValue.writec                 C   s:   | j sJ ‚| jrt|  ¡ ƒS tt d| j dd… ¡d ƒS )z$Return length of uncompressed value.ú<LéüÿÿÿNr   )r   r   Úlenr#   ÚintÚstructÚunpackr"   r   r   r   Ú__len__Q   s   
zCompressedValue.__len__c                 C   s   |   ¡  ¡ S )z.Behaves like splitlines() for a normal string.)r#   Ú
splitlinesr"   r   r   r   r/   Y   s   zCompressedValue.splitlines)NN)
Ú__name__Ú
__module__Ú__qualname__Ú__doc__r   r   r#   r   r.   r/   r   r   r   r   r
      s    

r
   c                   @   s°   e Zd Zd%dd„Zd&dd„Zdd	„ Zd
efdd„Zdd„ Ze	dd„ ƒZ
e	dd„ ƒZd'dd„Zd'dd„Zdi ddfdd„Zdd„ Zdd„ Ze	dd „ ƒZe	d!d"„ ƒZe	d#d$„ ƒZdS )(ÚProblemReportÚCrashNc                 C   s(   |du rt  ¡ }||dœ| _tƒ | _dS )zÞInitialize a fresh problem report.

        type can be 'Crash', 'Packaging', 'KernelCrash' or 'KernelOops'.
        date is the desired date/time string; if None (default), the
        current local time is used.
        N)ÚProblemTypeÚDate)ÚtimeÚasctimeÚdataÚsetÚold_keys)r   ÚtypeÚdater   r   r   r   `   s   zProblemReport.__init__Tc              	   C   s@  |   |¡ | j ¡  d}d}d}d}|rt|ƒ}nd}|D ]ë}	|	 d¡r¡|r+|s+d}q|dur3|dus5J ‚|r€t |	¡}
|rF|| |
¡7 }q|dkr_|jdkrW|
 d¡sWd|_	| j|
7  _q|
 d¡rtt
 t
j ¡}| |  |
¡¡}qt
 ¡ }|| |
¡7 }qt|ƒdkrŠ|d	7 }|	 d	¡r˜||	d
d… 7 }q||	d
d… 7 }q|r¯|r«|| ¡ 7 }d}d}|rÝ|durÕz| |¡ |  |¡| j|< |sÊd}W  n?W n tyÔ   Y n	w |  |¡| j|< |	 dd
¡\}}tsì| d¡}| ¡ }|dkr|dkrt| ¡ ƒ}d|_nd}d}q|dur|  |¡| j|< t| j ¡ ƒ| _dS )aë  Initialize problem report from a file-like object.

        If binary is False, binary data is not loaded; the dictionary key is
        created, but its value will be an empty string. If it is True, it is
        transparently uncompressed and available as dictionary byte array values.
        If binary is 'compressed', the compressed value is retained, and the
        dictionary value will be a CompressedValue object. This is useful if
        the compressed value is still useful (to avoid recompression if the
        file needs to be written back).

        file needs to be opened in binary mode.

        If key_filter is given, only those keys will be loaded.

        Files are in RFC822 format, but with case sensitive keys.
        NFó    Ú
compressedó    ó   ‹Tr   ó   
é   éÿÿÿÿó   :ÚASCIIó   base64)Ú_assert_bin_moder:   Úclearr;   Ú
startswithÚbase64Ú	b64decoder    r   r   r   ÚdecompressobjÚ	MAX_WBITSÚ_strip_gzip_headerr*   ÚendswithÚflushÚremoveÚ_try_unicodeÚKeyErrorÚsplitÚ_python2ÚdecodeÚstripr
   ÚencodeÚkeysr<   )r   r%   ÚbinaryÚ
key_filterÚkeyr   Ú	b64_blockÚbdÚremaining_keysÚliner'   r   r   r   Úloadn   s‚   







þÿ


€
zProblemReport.loadc              
   C   sè  |   |¡ t|tƒr|g}d}d}t|ƒ}i }d}d}	|D ]¶}
|
 d¡sÓ|
 dd¡\}}ts3| d¡}||vr8n›d||< | |¡ | 	¡ }|dkrÍd}d	||< zkd}t
tj ||¡d
ƒU}	|D ]J}
|
 d¡r©|durn|duspJ ‚|| r¨t |
¡}|r„|	 | |¡¡ q_| d¡rœt tj ¡}|	 | |  |¡¡¡ q_t ¡ }|	 | |¡¡ q_ W d  ƒ n1 s´w   Y  W n tyÌ   tdtj ||¡ ƒ‚w n|
 d¡r$q|rßtdd |¡ ƒ‚d| ¡ v ròtddd„ | ¡ D ƒ ƒ‚dS )zÖExtract only one binary element from the problem_report

        Binary elements like kernel crash dumps can be very big. This method
        extracts directly files without loading the report into memory.
        Nr?   rF   rD   rG   FrH   rA   Tr   rB   zunable to open %szCannot find %s in reportz, z%s has no binary contentc                 S   s   g | ]
\}}|d u r|‘qS ©Fr   )Ú.0ÚitemÚelementr   r   r   Ú
<listcomp>  s    z.ProblemReport.extract_keys.<locals>.<listcomp>)rI   Ú
isinstanceÚstrÚlistrK   rV   rW   rX   rS   rY   ÚopenÚosÚpathÚjoinrL   rM   r   r    r   rN   rO   rP   ÚIOErrorrU   ÚvaluesÚ
ValueErrorÚitems)r   r%   Úbin_keysÚdirr^   r   Úmissing_keysr_   r`   r   rb   r'   r   r   r   Úextract_keysÑ   sn   







€€ë€ÿ
Ù€(ÿÿzProblemReport.extract_keysÚreturnc              
   C   s˜   t  t j¡}z:z1zt  t jd¡ tt t | d ¡¡ƒW W t  t j|¡ W S  ty8   Y W t  t j|¡ W dS w t  t j|¡ w  t j	yK   Y dS w )zgGet timestamp (seconds since epoch) from Date field

        Return None if it is not present.
        ÚCr7   N)
ÚlocaleÚ	getlocaleÚLC_TIMEÚ	setlocaler+   r8   ÚmktimeÚstrptimerU   ÚError)r   Ú
orig_ctimer   r   r   Úget_timestamp  s   ýýÿzProblemReport.get_timestampc                 C   s   d|   ¡ v S )z~Check if the report has any keys which were not loaded.

        This could happen when using binary=False in load().
        N)rq   r"   r   r   r   Úhas_removed_fields#  s   z ProblemReport.has_removed_fieldsc                 C   s4   t |ƒtkr|D ]}|dk rt|ƒ ¡ s dS qdS )z0Check if the given strings contains binary data.é    TF)r=   ÚbytesÚchrÚisspace)ÚklassÚstringÚcr   r   r   Ú
_is_binary*  s   €zProblemReport._is_binaryc                 C   s>   t |ƒtkr|  |¡sz| d¡W S  ty   | Y S w |S )z)Try to convert bytearray value to unicodeúUTF-8)r=   r…   r‹   rX   ÚUnicodeDecodeError)rˆ   r   r   r   r   rT   4  s   ÿzProblemReport._try_unicodeFc              	   C   s¸  |   |¡ g }g }| j ¡ D ]?}|r|| jv rq| j| }t|dƒr3|  |¡r-| |¡ q| |¡ qt|tƒsHt	|ƒdkrH|d sH| |¡ q| |¡ q| 
¡  d|v ra| d¡ | dd¡ | 
¡  |D ]£}| j| }t|dƒsÖt	|ƒdkr„|d dur„|d }nd}t	|ƒdko|d }t|d d	ƒrž|d  ¡ }nt|d d
ƒ}	|	 ¡ }W d  ƒ n1 s´w   Y  |rÇt	|ƒdkrÇtd| ƒ‚|durÖt	|ƒ|krÖ| j|= qgt|tƒrà| d¡}| | d¡¡ d|v rû| d¡ | | dd¡¡ n
| d¡ | |¡ | d¡ qg|D ]K}| j| }d}d}
| ¡ }| | d¡¡ | d¡ t|tƒr@| t |j¡¡ | d¡ qd| d¡ d }| t |¡¡ | d¡ t d¡}t dtjtj tjd¡}t|dƒr|
t	|ƒ7 }
t ||¡}| |¡}|r| t |¡¡ | d¡ n˜t	|ƒdkr¢|d dur¢|d }t|d d	ƒr¯|d }	nt|d d
ƒ}		 |	 d¡}|
t	|ƒ7 }
t ||¡}|durã|
|krã| |¡ |  |¡ | j|= d}n|rü| |¡}|rû| t |¡¡ | d¡ nnq·t|d d	ƒs|	 !¡  t	|ƒdkr(|d r(|
dkr(td|t|d ƒf ƒ‚|r0|
|krX| "¡ }|rK|t# $d|d@ ¡7 }|t# $d|
d@ ¡7 }| t |¡¡ | d¡ qdS )a»  Write information into the given file-like object.

        If only_new is True, only keys which have been added since the last
        load() are written (i. e. those returned by new_keys()).

        If a value is a string, it is written directly. Otherwise it must be a
        tuple of the form (file, encode=True, limit=None, fail_on_empty=False).
        The first argument can be a file name or a file-like object,
        which will be read and its content will become the value of this key.
        'encode' specifies whether the contents will be
        gzip compressed and base64-encoded (this defaults to True). If limit is
        set to a positive integer, the file is not attached if it's larger
        than the given limit, and the entire key will be removed. If
        fail_on_empty is True, reading zero bytes will cause an IOError.

        file needs to be opened in binary mode.

        Files are written in RFC822 format.
        Úfindé   rD   r6   r   é   Né   r!   Úrbzdid not get any data for field rŒ   rG   rC   s   :
 s   
 s   : s
   : base64
 s
   ‹    ÿó    rA   é   Tr$   z)did not get any data for field %s from %sr(   l   ÿÿ )%rI   r:   r[   r<   Úhasattrr‹   Úappendri   r
   r*   ÚsortrS   Úinsertr!   rl   rp   rj   rZ   r   ÚreplaceÚtellrL   Ú	b64encoder   r   Úcrc32ÚcompressobjÚDEFLATEDrO   ÚDEF_MEM_LEVELÚcompressÚseekÚtruncateÚcloserR   r,   Úpack)r   r%   Úonly_newÚasckeysÚbinkeysÚkÚvÚlimitÚfail_on_emptyÚfÚsizeÚcurr_posÚgzip_headerÚcrcÚbcÚoutblockr'   r   r   r   r   ?  sÚ   








ÿ










ÿ

€







€î

€µzProblemReport.writec                 C   sˆ   t  |¡}z*t|dƒ}t  |d¡ |  |¡ | ¡  W |r't  ||j|jf¡ t  ||j	¡ dS |r<t  ||j|jf¡ t  ||j	¡ w )a  Add this report's data to an already existing report file.

        The file will be temporarily chmod'ed to 000 to prevent frontends
        from picking up a hal-updated report file. If keep_times
        is True, then the file's atime and mtime restored after updating.
        Úabr   N)
rm   Ústatrl   Úchmodr   r£   ÚutimeÚst_atimeÚst_mtimeÚst_mode)r   Ú
reportfileÚ
keep_timesÚstr¬   r   r   r   Úadd_to_existingå  s   



þzProblemReport.add_to_existingé   c                 C   s2  |   |¡ t| j ¡ ƒ}d}g }d|v r| d¡ | dd¡ |r;d}	|D ]}
|
|v r:| |
¡ | |	|
¡ |	d7 }	q%|D ]}|rG||v rGq=| j| }d}t|tƒrW|j}n`t	|dƒs¤d}t	|d dƒrj|d }nt
|d dƒ}| d	¡r{| ¡ }n$tƒ }tj|d
|dd}	 | d¡}|r•| |¡ n| ¡  nqˆ| ¡ }| ¡  n|  |¡r·| d	¡r±|}nt||ƒj}|råtddƒ}| d	¡rÌ|jdd|d n
|jdd|d	 d | |¡ t|ƒ | |¡ q=t|ƒ}t|ƒtkrõ| dd¡}t|tƒsüJ ‚t| ¡ ƒ}|dkr|dkr| ¡ }||d | d 7 }q=|dkrB||krB||d 7 }| d¡s5|d7 }||  ¡  !dd¡d 7 }q=t"|dd}|jdd|d d | |¡ q=t"|dd}| dd¡ | d|¡ t#ƒ }| $¡ D ]\}}| ||¡ qq|D ]}| %|¡ q| | &¡  'd¡¡ | d¡ dS )a”  Write MIME/Multipart RFC 2822 formatted data into file.

        file must be a file-like object, not a path.  It needs to be opened in
        binary mode.

        If a value is a string or a CompressedValue, it is written directly.
        Otherwise it must be a tuple containing the source file and an optional
        boolean value (in that order); the first argument can be a file name or
        a file-like object, which will be read and its content will become the
        value of this key.  The file will be gzip compressed, unless the key
        already ends in .gz.

        attach_treshold specifies the maximum number of lines for a value to be
        included into the first inline text part. All bigger values (as well as
        all non-ASCII ones) will become an attachment, as well as text
        values bigger than 1 kB.

        Extra MIME preamble headers can be specified, too, as a dictionary.

        skip_keys is a set/list specifying keys which are filtered out and not
        written to the destination file.

        priority_fields is a set/list specifying the order in which keys should
        appear in the destination file.
        Ú r6   r   rD   NrŽ   r!   r’   z.gzr   r   Tr$   Úapplicationzx-gzipzContent-DispositionÚ
attachment)ÚfilenamerŒ   r™   iè  z: Ú
z:
 z
 )Ú_charsetz.txtÚinlinerC   )(rI   Úsortedr:   r[   rS   r˜   ri   r
   r   r•   rl   rQ   r!   r   r   r   r   r£   r   r‹   r   Ú
add_headerÚset_payloadr   r–   r*   r=   r…   rX   rj   r/   ÚrstriprY   r™   r   r   rs   ÚattachÚ	as_stringrZ   )r   r%   Úattach_tresholdÚextra_headersÚ	skip_keysÚpriority_fieldsr[   ÚtextÚattachmentsÚcounterÚpriority_fieldr¨   r©   Úattach_valuer¬   ÚioÚgfr'   Úattr­   ÚlinesÚmsgÚar   r   r   Ú
write_mime÷  sœ   


€







ú





zProblemReport.write_mimec                 C   s¾   t |dƒsJ ‚| dd¡ dd¡ dd¡ ¡ std| ƒ‚t|tƒsXt |dƒsXt|tƒrRt|ƒdksDt|ƒdkrRt|ƒd	krR|d d
v rRt |d dƒsXt |d dƒsXtd| ƒ‚| j	 
||¡S )NÚisalnumÚ.r¿   ú-Ú_z[key '%s' contains invalid characters (only numbers, letters, '.', '_', and '-' are allowed)rD   r   r‘   )TFr   r!   zGvalue for key %s must be a string, CompressedValue, or a file reference)r•   r™   rÜ   rr   ri   r
   Útupler*   Ú	TypeErrorr:   Ú__setitem__)r   r¨   r©   r   r   r   râ   ~  s    ÿ0ÿÿzProblemReport.__setitem__c                 C   s   t | j ¡ ƒ| j S )z‘Return newly added keys.

        Return the set of keys which have been added to the report since it
        was constructed or loaded.
        )r;   r:   r[   r<   r"   r   r   r   Únew_keysŒ  s   zProblemReport.new_keysc                 C   s®   t r|  |¡S |d }d}|d@ r||| d 7 }|d@ r1|| dkr-|d7 }|| dks#|d7 }|d@ rI|| dkrE|d7 }|| dks;|d7 }|d@ rQ|d7 }||d	… S )
z0Strip gzip header from line and return the rest.r   é
   r‘   rD   é   r   é   r   N)rW   Ú_strip_gzip_header_py2©rˆ   rb   ÚflagsÚoffsetr   r   r   rP   ”  s&   
ÿÿz ProblemReport._strip_gzip_headerc                 C   s´   t |d ƒ}d}|d@ r||| d 7 }|d@ r0t || ƒdkr,|d7 }t || ƒdks |d7 }|d@ rLt || ƒdkrH|d7 }t || ƒdks<|d7 }|d@ rT|d7 }||d	… S )
z;Strip gzip header from line and return the rest. (Python 2)r   rä   r‘   rD   rå   r   ræ   r   N)Úordrè   r   r   r   rç   ¬  s"   ÿÿz$ProblemReport._strip_gzip_header_py2c                 C   s@   t rt|ƒtksd|jv sJ dƒ‚dS dS t|dƒrJ dƒ‚dS )z/Assert that given file object is in binary modeÚbz"file stream must be in binary modeÚencodingN)rW   r=   r   r   r•   )rˆ   r%   r   r   r   rI   Á  s   &zProblemReport._assert_bin_mode)r5   N)TNrd   )r0   r1   r2   r   rc   rw   r+   r‚   rƒ   Úclassmethodr‹   rT   r   r½   rÛ   râ   rã   rP   rç   rI   r   r   r   r   r4   _   s2    

c@
	


 
'
ÿ 

r4   )r3   rz   r   rL   r8   Úsysr   r,   rm   Úemail.encodersr   Úemail.mime.multipartr   Úemail.mime.baser   Úemail.mime.textr   rÕ   r   Úversionr	   r   rW   Úcollectionsr
   r4   r   r   r   r   Ú<module>   s    8@