
    j                     *    d dl Z d dlZd dlZd Zd ZdS )    Nc                    |d         }|d         dk    s|d         dk    r|d         }|d         }n|d         }|d         }|d         }|d         }d}|d         }	|                      |	|z   |z   |z              |dk    r|                     |          }
|
}d	}n&|d
k    r-|                     |          }t          j        |d          }d}n||k    r|                     |          }|}d}n|                                 }	 |                     |          }t          j        d          }|                    |          }|j        r|j        s|j        rt          d          d}nY# t          $ rL}t          j        |           |                      |           |                     |          }|}d}Y d}~nd}~ww xY w||fS )aP  
    Extracts a single file from the apk_file based on the information provided from the offset and the header_info.
    It takes into account that the compression method provided might not be STORED or DEFLATED! The returned
    'indicator', shows what compression method was used. Besides the standard STORED/DEFLATE it may return
    'DEFLATED_TAMPERED', which means that the compression method found was not DEFLATED(8) but it should have been,
    and 'STORED_TAMPERED' which means that the compression method found was not STORED(0) but should have been.

    :param apk_file: The APK file e.g. with open('test.apk', 'rb') as apk_file
    :type apk_file: bytesIO
    :param local_header_info: The local header dictionary info for that specific filename
    :type local_header_info: dict
    :param central_directory_info: The central directory entry for that specific filename
    :type central_directory_info: dict
    :return: Returns the actual extracted data for that file along with an indication of whether a static analysis evasion technique was used or not.
    :rtype: set(bytes, str)
    file_name_lengthcompressed_sizer   uncompressed_sizeextra_field_lengthcompression_method   $relative_offset_of_local_file_headerSTORED   iDEFLATEDSTORED_TAMPEREDzInvalid or non-pure deflateDEFLATED_TAMPEREDN)seekreadzlib
decompresstelldecompressobjeofunused_dataunconsumed_tail
ValueError	Exceptionloggingdebug)apk_filelocal_header_infocentral_directory_infofilename_lengthr   r   r   r   local_header_sizeoffsetuncompressed_dataextracted_data	indicatorcompressed_datacur_locc_objes                    [/home/ubuntu/.hermes/hermes-agent/venv/lib/python3.11/site-packages/apkInspector/extract.py!extract_file_based_on_header_infor+      s(   " ((:;O*+q004EFY4Z^_4_4_01BC23FG+,=>-.AB*+?@*+?@#$JKFMM&,,>ASSTTTQ$MM*;<<*			q	 	 "--88#>>			-	-	-"--(9::(%		--//	*&mmO<<O&s++E"--o>>N9 @ 1 @U5J @ !>???+II 	* 	* 	*M!MM'"""&mm,=>>O,N)IIIIII	* 9$$s   A$E( (
F>2AF99F>c                 |   	 t           j                            |          rt          d           dS t          j        |d           |                                D ]\  }}|st          | ||         |          d         }t           j                            ||          }t          j        t           j                            |          d           t          |d          5 }|
                    |           ddd           n# 1 swxY w Y   dS # t          $ r}	t          d|	            Y d}	~	d	S d}	~	ww xY w)
a  
    Extracts all files from an APK based on the entries detected in the central_directory_entries.

    :param apk_file: The APK file e.g. with open('test.apk', 'rb') as apk_file
    :type apk_file: bytesIO
    :param central_directory_entries: The dictionary with all the entries for the central directory
    :type central_directory_entries: dict
    :param local_header_entries: The dictionary with all the local header entries
    :type local_header_entries: dict
    :param output_dir: The output directory where to save the files.
    :type output_dir: str
    :return: Returns 0 if no errors, 1 if an exception and 2 if the output directory already exists
    :rtype: int
    z4Extraction aborted. Output directory already exists.   T)exist_okr   wbNzError extracting files:    )ospathexistsprintmakedirsitemsr+   joindirnameopenwriter   )
r   central_directory_entrieslocal_header_entries
output_dirfilenamecd_header_infor$   output_pathoutput_filer)   s
             r*   (extract_all_files_from_central_directoryrB   D   s   7>>*%% 	HIII1
J....(A(G(G(I(I 	2 	2$Hn  2(<PQY<Z\jkklmn  ',,z8<<KK44tDDDDk4(( 2K!!.1112 2 2 2 2 2 2 2 2 2 2 2 2 2 2q   ,,,---qqqqqsA   .D B2D $D:D D
	
D D
	D 
D;D66D;)r   r   r1   r+   rB        r*   <module>rE      sI      				;% ;% ;%|( ( ( ( (rD   