
    G/Ph@                    \   d Z ddlm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ZdZg d	Zd
ddddddZej                            ej                            e                    Z edd          Z edd          Z G d de          Zej                            ed          fdCdZdDdZ e            \  ZZZZdEdZ e            \  Z Z!dFdGd!Z"dFdHd%Z#dFdId)Z$dJd+Z%d, Z&d- Z'dKd.Z(dLdMd0Z)dNdOd4Z*dNdPd5Z+dQd6Z,dFdRd7Z-dFdRd8Z.d9 Z/ddddddd:Z0dSdTdAZ1e2dBk    r e/             dS dS )Uu  
puremagic is a pure python module that will identify a file based off it's
magic numbers. It is designed to be minimalistic and inherently cross platform
compatible, with no imports when used as a module.

© 2013-2025 Chris Griffith - License: MIT (see LICENSE)

Acknowledgements
Gary C. Kessler
    For use of his File Signature Tables, available at:
    http://www.garykessler.net/library/file_sigs.html
    )annotationsN)	unhexlify)
namedtuple)chainzChris Griffithz1.29)
magic_filemagic_stringmagic_stream	from_filefrom_stringfrom_streamext_from_filename	PureErrormagic_footer_arraymagic_header_arraymulti_part_dictwhat	PureMagicPureMagicWithConfidencebmpjpegrasttiff)dibjfifjpgrstsuntifr   
byte_matchoffset	extension	mime_typenamer   )r    r!   r"   r#   r$   
confidencec                      e Zd ZdZdS )r   z.Do not have that type of file in our databanksN)__name__
__module____qualname____doc__     N/var/www/html/test/jupyter/venv/lib/python3.11/site-packages/puremagic/main.pyr   r   F   s        8888r,   r   zmagic_data.jsonfilenameos.PathLike | strreturnVtuple[list[PureMagic], list[PureMagic], list[PureMagic], dict[bytes, list[PureMagic]]]c                   t          | d          5 }t          j        |          }ddd           n# 1 swxY w Y   t          d |d         D             d           }t          d |d	         D             d
           }d |d         D             }i }|d                                         D ]4\  }}d |D             |t          |                    d                    <   5||||fS )zRead the magic fileutf-8)encodingNc              3  4   K   | ]}t          |          V  d S N_create_puremagic.0xs     r-   	<genexpr>z_magic_data.<locals>.<genexpr>P   +      DDq'**DDDDDDr,   headersc                    | j         S r6   r    r;   s    r-   <lambda>z_magic_data.<locals>.<lambda>P   
    TUT` r,   )keyc              3  4   K   | ]}t          |          V  d S r6   r7   r9   s     r-   r<   z_magic_data.<locals>.<genexpr>Q   r=   r,   footersc                    | j         S r6   r@   rA   s    r-   rB   z_magic_data.<locals>.<lambda>Q   rC   r,   c                ,    g | ]}t          |          S r+   r7   r9   s     r-   
<listcomp>z_magic_data.<locals>.<listcomp>R   s!    GGG1#A&&GGGr,   extension_onlyz
multi-partc                ,    g | ]}t          |          S r+   r7   r9   s     r-   rI   z_magic_data.<locals>.<listcomp>U   s#    GrGrGrabHYZ[H\H\GrGrGrr,   ascii)openjsonloadsorteditemsr   encode)	r.   fdatar>   rF   
extensionsmulti_part_extensions
file_matchoption_lists	            r-   _magic_datarY   J   sQ    
h	)	)	) Qy||              DDDODDDJ`J`aaaGDDDODDDJ`J`aaaGGG5E0FGGGJ#'#5#;#;#=#= s s
KGrGrfqGrGrGri
(9(9'(B(BCCDDGZ)>>>s   377r;   listc                    t          t          | d                             d                    | d         | d         | d         | d                   S )Nr   rL               r   )r   r   rR   rA   s    r-   r8   r8   Y   sP    QqT[[1122tA$A$qT   r,   tuple[int, int]c            	        t          d t          D                       } t          d t          D                       }t                                          D ]t}|D ]o}|j        dk     r8t          |t          |j                  t          |j                  z             }Et          | t          |j                  |j        z             } pu| |fS )z3The length of the largest magic string + its offsetc                F    g | ]}t          |j                  |j        z   S r+   )lenr    r!   r9   s     r-   rI   z _max_lengths.<locals>.<listcomp>h   s)    VVVaS..9VVVr,   c                `    g | ]+}t          |j                  t          |j                  z   ,S r+   )rc   r    absr!   r9   s     r-   rI   z _max_lengths.<locals>.<listcomp>i   s/    [[[1S..QX>[[[r,   r   )	maxr   r   r   valuesr!   rc   r    re   )max_header_lengthmax_footer_lengthoptionsoptions       r-   _max_lengthsrl   f   s    VVCUVVVWW[[HZ[[[\\"))++ c c 	c 	cF}q  $'(93v?P;Q;QTWX^XeTfTf;f$g$g!!$'(93v?P;Q;QTZTa;a$b$b!!		c ///r,   list[PureMagicWithConfidence]c           	        g }| D ]}t          |j                  dk    rdn#t          dt          |j                             }|dk    rr|j        k    rd}|                    t          dd|i|                                           |srfdt          D             }|st          d          t          |d	 d
          S )z:Rough confidence based on string length and file extension	   g?z0.皙?g?r%   c                f    g | ]-}|j         k    t          dd di|                                .S )r%   rp   r+   )r"   r   _asdict)r:   	magic_rowexts     r-   rI   z_confidence.<locals>.<listcomp>   sP     
 
 
i))) $JJsJi6G6G6I6IJJ)))r,   zCould not identify filec                8    | j         t          | j                  fS r6   )r%   rc   r    rA   s    r-   rB   z_confidence.<locals>.<lambda>   s    !,AL8I8I)J r,   TrD   reverser+   )
rc   r    floatr"   appendr   rr   extension_only_arrayr   rP   )matchesrt   resultsmatchcons    `   r-   _confidencer   x   s   G S S)**a//ccU;WEDT@U@U;W;W5X5X#::#:#"8"8C.QQ#QQQRRRR 
s 

 
 
 
1
 
 
  31222'JJTXYYYYr,   headerbytesfooterc                   g }t           D ]a}|j        }|j        t          |j                  z   }|t          |           k    r9| ||         |j        k    r|                    |           bt
          D ]_}|j        }|j        t          |j                  z   }|dk    r
|||         n	||d         }||j        k    r|                    |           `t                      }|D ]4}	|	j        t          v r"t          |	j                 D ]}|j        }|j        t          |j                  z   }|j        dk     rn|dk    r
|||         n	||d         }||j        k    rH|                    t          |	j        |j        z   |j        |j
        |j        |j                             |t          |           k    r| ||         |j        k    rH|                    t          | |	j        |         |j        |j
        |j        |j                             6|                    t          |                     t          ||          S )z/Attempt to identify 'data' by its magic numbersr   Nr   )r   r!   rc   r    ry   r   setr   addr   r"   r#   r$   extendrZ   r   )
r   r   rt   r{   rs   startend
match_areanew_matchesmatcheds
             r-   _identify_allr      s|   
 G' & &	 Y%9!:!::V%)	 444NN9%%%' & &	 Y%9!:!::*-((VE#I&&uvv
---NN9%%%%%K  00,W-?@  	!(&Y-A)B)BB#a''69Qhhc	!2!2F566NJ!Y%999#%+2+=	@T+T'0'7*3*=*3*=%.^     S[[(( eCi(I,@@@#%+1'.32F+G'0'7*3*=*3*=%.^     NN4$$%%%w$$$r,   mimeboolstrc                    | st          d          t          | ||          d         }|r|j        S t          |j        t
                    s|j        n|d         j        S )z=Discover what type of file it is based on the incoming stringInput was emptyr   )
ValueErrorr   r#   
isinstancer"   rZ   )r   r   r   rt   infos        r-   _magicr      sc     ,*+++--a0D ~!+DND!A!AX4>>tAwGXXr,   tuple[bytes, bytes]c                P   t          | d          5 }|                    t                    }	 |                    t           t
          j                   n%# t          $ r |                    d           Y nw xY w|                                }ddd           n# 1 swxY w Y   ||fS )z"Grab the start and end of the filerbr   N)rM   readmax_headseekmax_footosSEEK_ENDOSError)r.   finheadfoots       r-   _file_detailsr      s    	h		 xx!!	HHhY,,,, 	 	 	HHQKKKKK	xxzz               :s4   B&ABA63B5A66BB Bc                @    | dt                    | t           d         fS )z$Grab the start and end of the stringN)r   r   )strings    r-   _string_detailsr      s!    )8)fhYZZ000r,   c                8   |                      t                    }	 |                     t           t          j                   n,# t          t          f$ r |                     d           Y nw xY w|                                  }|                     d           ||fS )z$Grab the start and end of the streamr   )r   r   r   r   r   r   r   r   )streamr   r   s      r-   _stream_detailsr      s    ;;x  DXIr{++++Z    A ;;==D
KKNNN:s   &A &A,+A,c                N   	 t          |                                                               dd          \  }}n# t          $ r Y dS w xY wd| }d t	          t
          t                    D             }|dd                             d          r|dd         |z   }||v r|S |S )zScan a filename for its extension.

    :param filename: string of the filename
    :return: the extension off the end (empty string if it can't find one)
    .r\    c                    g | ]	}|j         
S r+   )r"   r9   s     r-   rI   z%ext_from_filename.<locals>.<listcomp>   s    SSSSSSr,   N)r   lowerrsplitr   r   r   r   
startswith)r.   basert   all_extslong_exts        r-   r   r      s    MM''))00a88	cc   rr
c))CSSU+=?Q%R%RSSSHBCCyC   9s?xOJs   8; 
A	A	Fc                d    t          |           \  }}t          |||t          |                     S )a  Opens file, attempts to identify content based
    off magic number and will return the file extension.
    If mime is True it will return the mime type instead.

    :param filename: path to file
    :param mime: Return mime, not extension
    :return: guessed extension or mime
    )r   r   r   )r.   r   r   r   s       r-   r
   r
     s2     x((JD$$d$5h$?$?@@@r,   r   str | bytesos.PathLike | str | Nonec                    t          | t                    r|                     d          } t          |           \  }}|rt	          |          nd}t          ||||          S )a  Reads in string, attempts to identify content based
    off magic number and will return the file extension.
    If mime is True it will return the mime type instead.
    If filename is provided it will be used in the computation.

    :param string: string representation to check
    :param mime: Return mime, not extension
    :param filename: original filename
    :return: guessed extension or mime
    r3   N)r   r   rR   r   r   r   )r   r   r.   r   r   rt   s         r-   r   r     sd     &# (w'' ((JD$)1
;
H
%
%
%tC$dC(((r,   c                p    t          |           \  }}|rt          |          nd}t          ||||          S )a  Reads in stream, attempts to identify content based
    off magic number and will return the file extension.
    If mime is True it will return the mime type instead.
    If filename is provided it will be used in the computation.

    :param stream: stream representation to check
    :param mime: Return mime, not extension
    :param filename: original filename
    :return: guessed extension or mime
    N)r   r   r   )r   r   r.   r   r   rt   s         r-   r   r   $  sA     !((JD$)1
;
H
%
%
%tC$dC(((r,   c                    t          |           \  }}|st          d          	 t          ||t          |                     }n# t          $ r g }Y nw xY w|                    d d           |S )z
    Returns list of (num_of_matches, array_of_matches)
    arranged highest confidence match first.

    :param filename: path to file
    :return: list of possible matches, highest confidence first
    r   c                    | j         S r6   r%   rA   s    r-   rB   zmagic_file.<locals>.<lambda>C      AL r,   Trv   )r   r   r   r   r   sort)r.   r   r   r   s       r-   r   r   4  s     x((JD$ ,*+++T4):8)D)DEE   II(($I777Ks   A AAc                    | st          d          t          |           \  }}|rt          |          nd}t          |||          }|                    d d           |S )aC  
    Returns tuple of (num_of_matches, array_of_matches)
    arranged highest confidence match first
    If filename is provided it will be used in the computation.

    :param string: string representation to check
    :param filename: original filename
    :return: list of possible matches, highest confidence first
    r   Nc                    | j         S r6   r   rA   s    r-   rB   zmagic_string.<locals>.<lambda>V  r   r,   Trv   )r   r   r   r   r   )r   r.   r   r   rt   r   s         r-   r   r   G  st      ,*+++ ((JD$)1
;
H
%
%
%tCtS))DII(($I777Kr,   c                    t          |           \  }}|st          d          |rt          |          nd}t          |||          }|                    d d           |S )a>  Returns tuple of (num_of_matches, array_of_matches)
    arranged highest confidence match first
    If filename is provided it will be used in the computation.

    :param stream: stream representation to check
    :param filename: original filename
    :return: list of possible matches, highest confidence first
    r   Nc                    | j         S r6   r   rA   s    r-   rB   zmagic_stream.<locals>.<lambda>h  r   r,   Trv   )r   r   r   r   r   )r   r.   r   r   rt   r   s         r-   r	   r	   Z  st     !((JD$ ,*+++)1
;
H
%
%
%tCtS))DII(($I777Kr,   c            
     J   dd l }ddlm}  |d          }|                    ddddd	
           |                    ddddd
           |                    dd           |                    | r| n|j        dd                    } | j        D ]}t          j        	                    |          st          d| d           6	 t          d| dt          || j                              n## t          $ r t          d| d           Y w xY w| j        rt          |          }t          dt!          |                      t#          |          D ]\  }}|dk    rt          d           nt          d|            t          d|j                    t          dt'          |j        dz             d           t          d|j                    t          d |j                    t          d!|j                    t          d"|j         d#           ʐd S )$Nr   )ArgumentParserzpuremagic is a pure python file identification module.It looks for matching magic numbers in the file to locate the file type. )descriptionz-mz--mime
store_truer   z)Return the mime type instead of file type)actiondesthelpz-vz--vverbosezPrint verbose outputfiles+)nargsr\   zFile 'z' does not exist!'z' : z' : could not be IdentifiedzTotal Possible Matches: z
	Best Matchz	Alertnative Match #z	Name: z	Confidence: d   %z	Extension: z	Mime Type: z	Byte Match: z		Offset: 
)sysargparser   add_argument
parse_argsargvr   r   pathexistsprintr
   r   r   r   r   rc   	enumerater$   intr%   r"   r#   r    r!   )argsr   r   parserfnr{   iresults           r-   command_line_entryr   l  s   JJJ''''''^X  F 8     eLyOefff
s+++T;TTsx|<<Dj 6 6w~~b!! 	02000111	8b88iDI66889999 	 	 	5b555666H	 < 	6 nnG;S\\;;<<<&w// 
6 
6	666*++++5!55666...///Fs6+<s+B'C'CFFFGGG8f&6889998f&688999:v'8::;;;46=4445555-6 6s   (C//DD)s
   ______Exifs
   ______JFIFs   IIs
   II\x2a\x00s   MMs
   MM\x00\x2aTfilehbytes | Noneimghdr_strict
str | Nonec                T   t          |t                    rt          d          |r |rt                              |          }|r|S 	 |rt          |          nt          | pd                              d          }n# t          $ r Y dS w xY wt                              ||          S )a  A drop-in replacement for `imghdr.what()` which was removed from the standard
    library in Python 3.13.

    Usage:
    ```python
    # Replace...
    from imghdr import what
    # with...
    from puremagic import what
    # ---
    # Or replace...
    import imghdr
    ext = imghdr.what(...)
    # with...
    import puremagic
    ext = puremagic.what(...)
    ```
    imghdr documentation: https://docs.python.org/3.12/library/imghdr.html
    imghdr source code: https://github.com/python/cpython/blob/3.12/Lib/imghdr.py

    imghdr_strict enables bug-for-bug compatibility between imghdr.what() and puremagic.what() when the imghdr returns
    a match but puremagic returns None.  We believe that imghdr is delivering a "false positive" in each of these
    scenerios but we want puremagic.what()'s default behavior to match imghdr.what()'s false positives so we do not
    break existing applications.

    If imghdr_strict is True (the default) then a lookup will be done to deliver a matching result on all known false
    positives.  If imghdr_strict is False then puremagic's algorithms will determine the image type.  True is more
    compatible while False is more correct.

    NOTE: This compatibility effort only deals false positives and we are not interested to track the opposite
    situation where puremagic's deliver a match while imghdr would have returned None.  Also, puremagic.what() can
    recognize many more file types than the twelve image file types that imghdr focused on.
    z:h must be bytes, not str.  Consider using bytes.fromhex(h)r   r   N)
r   r   	TypeErrorimghdr_bug_for_buggetr   r
   lstripr   imghdr_exts)r   r   r   rt   s       r-   r   r     s    D !S VTUUU ]  $$Q'' 	J!"={1~~~	$*"(=(=EEcJJ   tt??3$$$s   5A> >
BB__main__)r.   r/   r0   r1   )r;   rZ   r0   r   )r0   r`   r6   )r0   rm   )r   r   r   r   r0   rm   )r   r   r   r   r   r   r0   r   )r.   r/   r0   r   )r.   r/   r0   r   )F)r.   r/   r   r   r0   r   )FN)r   r   r   r   r.   r   r0   r   )r   r   r.   r   r0   r   )r.   r/   r0   rm   )r.   r   r0   rm   )NT)r   r   r   r   r   r   r0   r   )3r*   
__future__r   rN   r   binasciir   collectionsr   	itertoolsr   
__author____version____all__r   r   abspathdirname__file__herer   r   LookupErrorr   joinrY   r8   r   r   rz   r   rl   r   r   r   r   r   r   r   r   r   r
   r   r   r   r   r	   r   r   r   r'   r+   r,   r-   <module>r      sM    # " " " " "  				       " " " " " "      
  $ VF6RXaghh	wrwx0011J	 		 %*
 
 9 9 9 9 9 9 9 9
 #%',,t5F"G"G? ? ? ? ?    Q\P[P]P] M &(<o0 0 0 0 "\^^ (Z Z Z Z Z,6% 6% 6% 6% 6%rY Y Y Y Y	 	 	 	1 1 1

 
 
   *A A A A A) ) ) ) )$) ) ) ) )    &    &    $+6 +6 +6^   ,% ,% ,% ,% ,%^ z r,   