h dZddlmZmZmZmZmZmZmZddl Z ddl Z ddl Z ddl Z ddl Z ddlZddlmZmZddlmZddlmZmZmZmZmZmZmZmZddlmZddlmZm Z m!Z!dd l"m#Z#m$Z$dd l%m&Z&dd l'm(Z(dd l)m*Z*ee+ee+ee+d ffZ,ee+ee+fZ-GddZ.Gdde.Z/Gdde/Z0Gdde/Z1Gdde.Z2Gdde2Z3Gdde2Z4Gdde4Z5Gdde3Z6Gd d!e2Z7d"e8d#e9fd$Z:Gd%d&Z;Gd'd(e j<Z=Gd)d*Z>dS)+aRepresentation of the ISO7816-4 filesystem model. The File (and its derived classes) represent the structure / hierarchy of the ISO7816-4 smart card file system with the MF, DF, EF and ADF entries, further sub-divided into the EF sub-types Transparent, Linear Fixed, etc. The classes are intended to represent the *specification* of the filesystem, not the actual contents / runtime state of interacting with a given smart card. )castOptionalIterableListDictTupleUnionN) CommandSetwith_default_category)toBytes)h2bb2his_hexauto_int auto_uint8 auto_uint16 is_hexstr JsonEncoder)bertlv_parse_one) filter_dictparse_constructbuild_construct)sw_match decomposeATR)js_path_modify)SimCardCommands) SwMatchError.ceZdZdZgdZdgZ d'dedededed ed d ed d eefdZ dZ de deefdZ d(de defdZ d(de deefdZdedfdZdddeedfdZdedfdZdgfdedeedffdZdgfdeedeedffdZgfdeedffdZgfdeefdZd efd!Zd"Zd#eefd$Zed%e fd&ZdS))CardFilezBase class for all objects in the smart card filesystem. Serve as a common ancestor to all other file types; rarely used directly. ).../MF3f00NfidsfidnamedescparentCardDFprofile CardProfileservicecTt|ts|td|r|}||_||_||_||_||_|jr,|j|kr!|jr|j |||_ ||_ g|_ dS)a Args: fid : File Identifier (4 hex digits) sfid : Short File Identifier (2 hex digits, optional) name : Brief name of the file, like EF_ICCID desc : Description of the file parent : Parent CardFile object within filesystem hierarchy profile : Card profile that this file should be part of service : Service (SST/UST/IST) associated with the file Nzfid is mandatory) isinstanceCardADF ValueErrorlowerr%r&r'r(r)add_filer+r-shell_commands)selfr%r&r'r(r)r+r-s >/home/jenkins/workspace/simtester-sanitize/pySim/filesystem.py__init__zCardFile.__init__=s$(( 1S[/00 0  ))++C    ; '4;$..48. K  & & &   c,|jr|jS|jSNr'r%r5s r6__str__zCardFile.__str__]s 9 9 8Or8 prefer_namereturnc0|r|jr|jS|jSr:r;r5r>s r6 _path_elementzCardFile._path_elementcs"  49 9 8Or8TcRd||S)zReturn fully qualified path to file as string. Args: prefer_name : Preferably build path of names; fall-back to FIDs as required r")joinfully_qualified_pathrAs r6fully_qualified_path_strz!CardFile.fully_qualified_path_stris$ xx11+>>???r8c|jr&|j|kr|j|}ng}||}|r|||S)zReturn fully qualified path to file as list of FID or name strings. Args: prefer_name : Preferably build path of names; fall-back to FIDs as required )r)rErBappend)r5r>retelems r6rEzCardFile.fully_qualified_pathqsh ; 4;$..+22;??CCC!!+..   JJt    r8c|jr%|j|kr|j}ng}|r|||S)zLReturn fully qualified path to file as list of CardFile instance references.)r)fully_qualified_path_fobjrH)r5rIs r6rLz"CardFile.fully_qualified_path_fobjsQ ; 4;$..+7799CCC   JJt    r8targetcd}||kr|gS|}|}g}||D]}||t dt |dz D]L}||}||kr<||dzdD]} || ||ddccSMdS)zTBuild the relative sequence of files we need to traverse to get from us to 'target'.cttdt|D])}t||tr ||dcS*|S)Nr)reversedrangelenr/r0) inter_pathis r6 clip_pathz0CardFile.build_select_path_to..clip_paths^eAs:7788 * *jmW55*%abb>)))* r8rN)get_mfrLreverserHrQrR) r5rMrU cur_fqpath target_fqpathrScerTtete2s r6build_select_path_tozCardFile.build_select_path_tos*     V]]__ $ $8O3355 88::   5 5B   b ! ! !1c-00233 5 5"1%88,QqSTT2//"))#....$9Z^4444444  5tr8CardMFc|jdS|}|jr$|j|kr|j}|jr |j|ktt|S)z(Return the MF (root) of the file system.N)r)rr_)r5nodes r6rWzCardFile.get_mfsY ; 4k dkT11;Dk dkT11FD!!!r8aliasci}|r|||i|jr&|gksd|vr||j|i|jr&|gksd|vr||j|i|S)amReturn a dict of {'identifier': self} tuples. Args: alias : Add an alias with given name to 'self' flags : Specify which selectables to return 'FIDS' and/or 'NAMES'; If not specified, all selectables will be returned. Returns: dict containing reference to 'self' for all identifiers. FIDSFNAMES)updater%r'r5rbflagsselss r6_get_self_selectableszCardFile._get_self_selectabless  ' KK & & & 8 *"% KK4( ) ) ) 9 +%2++U):): KKD) * * * r8ci}|jr |j|kr|S|r|||ji|jjr0|gksd|vr&||jj|ji|jjr0|gksd|vr&||jj|ji||jd||S)Nrdre)r)rfr%r'_get_parent_selectablesrgs r6rlz CardFile._get_parent_selectabless{ dkT11K  . KK , - - - ;? 8 v KK$+6 7 7 7 ;  9"E0A0A KK)4;7 8 8 8 DK77eDDEEE r8ci}|gksd|vr|d|}|gksd|vr)||d||gksd|vrh|}|rR|||||||S)aReturn a dict of {'identifier': File} that is selectable from the current file. Args: flags : Specify which selectables to return 'FIDS' and/or 'NAMES'; If not specified, all selectables will be returned. Returns: dict containing all selectable items. Key is identifier (string), value a reference to a CardFile (or derived class) instance. SELFr!PARENTr r#)rh)rjrfrlrWget_app_selectables)r5rhrimfs r6get_selectableszCardFile.get_selectabless B;;&E//--c599D B;;(e++ KK44T5AA B B B B;;$%--B A B4454AABBB B222??@@@ r8c||}t|}||S)aAReturn a dict of {'identifier': File} that is selectable from the current file. Args: flags : Specify which selectables to return 'FIDS' and/or 'NAMES'; If not specified, all selectables will be returned. Returns: list containing all selectable names. )rrlistkeyssort)r5rhrisel_keyss r6get_selectable_nameszCardFile.get_selectable_namess>##E** $$ r8data_hexcH|jr|j|SdS)zxDecode the response to a SELECT command. Args: data_hex: Hex string of the select response N)r)decode_select_response)r5rys r6r{zCardFile.decode_select_responses1 ; @;55h?? ? @ @r8cb|jr|jS|jr|jSdS)zGet the profile associated with this file. If this file does not have any profile assigned, try to find a file above (usually the MF) in the filesystem hirarchy that has a profile assigned N)r+r) get_profiler<s r6r}zCardFile.get_profile s; < <  ; -;**,, ,tr8servicesc,|jdSt|jtr |j|vSt|jtr|jD] }||vrdS dSt|jtr|jD] }||vrdS dSt d)z[Assuming the provided list of activated services, should this file exist and be activated?.NTFz0self.service must be either int or list or tuple)r-r/intrttupler1)r5r~ss r6should_exist_for_servicesz"CardFile.should_exist_for_servicess < 4 dlC ( ( ,<8+ + dlD ) ) \  ==44!5 dlE * * \ ! !H}} 55%4KLLLr8as_jsonc0dt|jzS)a Export file contents in the form of commandline script. This method is meant to be overloaded by a subclass in case any exportable contents are present. The generated script may contain multiple command lines separated by line breaks ("\n"), where the last commandline shall have no line break at the end (e.g. "update_record 1 112233\nupdate_record 1 445566"). Naturally this export method will always refer to the currently selected file of the presented lchan. z# %s has no exportable contentsstr selected_filerlchans r6exportzCardFile.export.s13u7J3K3KKKr8)NNNNNNN)T)__name__ __module__ __qualname____doc__RESERVED_NAMES RESERVED_FIDSrrCardFileServicer7r=boolrBrFrrErLr^rWrrjrlrrrxr{r}rr staticmethodrr8r6rr6s,++NHMX\W[6:!!C!c!!RU!!(+!=Em=T!"?3!!!!@ (3- @@D@C@@@@   S    4 +;:(4 CS:T<"*""""26R3DjDY&>B  Xc] PTUXZdUdPe    %'4Z+@2*,  S     @s @ @ @ @   M$s)MMMM*LLLL\LLLr8rc&eZdZdZedGddeZfdZfdZdZ dZ dd e d e fd Z dd ee d e fdZgfdeffd Zdeedee fdZdeedee fdZdedee fdZxZS)r*zWDF (Dedicated File) in the smart card filesystem. Those are basically sub-directories.zDF/ADF CommandsceZdZdS)CardDF.ShellCommandsN)rrrrr8r6 ShellCommandsr=s r8rc t|tsd|vrtdtjdi|i|_|g|_i|_dS)Nr%zfid is mandatory for all DFr) r/r0 TypeErrorsuperr7childrenrr4files_by_servicer5kwargs __class__s r6r7zCardDF.__init__Asx$(( ?F"" =>>>""6""" #11334 "r8cJdtzS)NzDF(%s)rr=r5rs r6r=zCardDF.__str__K577??,,--r8c|jsdSt|jtr5|j|jg|dSt|jt r:|jD]0}|j|g|1dSt|jtr:|jD]0}|j|g|1dSt)z;Add a child (DF/EF) to the files_by_services of the parent.N) r-r/rr setdefaultrHrtrr1)r5childr-s r6_add_file_serviceszCardDF._add_file_servicesNs}  F emS ) )   ! , ,U]B ? ? F Fu M M M M M  t , ,  = L L%00"==DDUKKKK L L  u - -  = L L%00"==DDUKKKK L L r8c|jrdS|jD].}t|tr|rdS/dS)NT)r-rvaluesr/r* _has_service)r5cs r6rzCardDF._has_service]sd < 4%%''  A!V$$ >>## 44  r8Frignore_existingc:t|tstdt|jddst d|jz|jtjvrt d|jz|jtjvrt d|jz|j|j vr|rdSt d|jd || |j rt d |j d || |jr|rdSt d |jd |||j |j<||_ ||t|tr|j D]}||t|trT|j D]:}t|tr#|rt d ;dSdS) zAdd a child (DF/EF) to this DF. Args: child: The new DF/EF to be added ignore_existing: Ignore, if file with given FID already exists. Old one will be kept. zExpected a File instance)minlenmaxlenzFile name %s is not a valid fidzFile name %s is a reserved namezFile fid %s is a reserved fidNzFile with given fid z already exists in zFile with given sfid zFile with given name z1TODO: implement recursive service -> file mapping)r/rrrr%r1r'rrrlookup_file_by_sfidr&lookup_file_by_namer)rr*rr)r5rrrgcs r6r3zCardDF.add_fileesa %** 8677 7ei!444 N>%)LMM M :0 0 0>%*MNN N 9. . .< JKK K 9 % % *AFDDQSS S  # #EJ / / U*BG***ddSUU U  # #EJ / / U *BG***ddSUU U#( ei   &&& eV $ $ f^**,, f f''***a((fj//11ff%b&11f!00f&01d&e&e e f f f fr8rc<|D]}|||dS)zAdd a list of child (DF/EF) to this DF Args: children: List of new DF/EFs to be added ignore_existing: Ignore, if file[s] with given FID already exists. Old one[s] will be kept. N)r3)r5rrrs r6 add_fileszCardDF.add_filess4 2 2E MM% 1 1 1 1 2 2r8r?cJt|}|gksd|vr6|d|jD|gksd|vr6|d|jD|S)Return a dict of {'identifier': File} that is selectable from the current DF. Args: flags : Specify which selectables to return 'FIDS' and/or 'NAMES'; If not specified, all selectables will be returned. Returns: dict containing all selectable items. Key is identifier (string), value a reference to a CardFile (or derived class) instance. rdc,i|]}|j |j|Srr%.0xs r6 z*CardDF.get_selectables..s#KKKaQUKKKKr8rec,i|]}|j |j|Srr'rs r6rz*CardDF.get_selectables..s#MMMqafMMMMr8)rrrrfrrr5rhrirs r6rrzCardDF.get_selectablessww&&u-- B;;&E// KKKK4=+?+?+A+AKKK L L L B;;(e++ KKMMDM,@,@,B,BMMM N N N r8r'cr|dS|jD]}|jr|j|kr|cSdS)z.Find a file with given name within current DF.N)rrr')r5r'rTs r6rzCardDF.lookup_file_by_namesL <4%%''  Av !&D..tr8r&c|dS|jD]+}|jtt |kr|cS,dS)z7Find a file with given short file ID within current DF.N)rrr&rr)r5r&rTs r6rzCardDF.lookup_file_by_sfidsU <4%%''  AvSYY''(tr8r%c2||jvr |j|SdS)z1Find a file with given file ID within current DF.N)r)r5r%s r6lookup_file_by_fidzCardDF.lookup_file_by_fids! $-  =% %tr8F)rrrrr r rr7r=rrrrr3rrdictrrrrrrr __classcell__rs@r6r*r*:saa,--       .- #####.....      &f&fh&f&f&f&f&fP22(8"42t2222%'4$ (8:L (8:Lchx.@r8r*cveZdZdZfdZdZd dZdZgfdeffd Z gfdefd Z d e e de fd ZxZS)r_z-MF (Master File) in the smart card filesystemc |dd|dd|dd||d<tjdi|i|_dS) Nr%r$r'r#r(zMaster File (directory root)r)r)rrr7 applicationsrs r6r7zCardMF.__init__s{%(((&$'''&"@AAAx""6"""r8cd|jzS)NzMF(%s)rr<s r6r=zCardMF.__str__s48$$r8appr0ct|tstd|j|jvrt d|jz||j|j<||_dS)zAdd an Application to the MFzExpected an ADF instancezAID %s already existsN)r/r0raidrr1r))r5rs r6add_application_dfzCardMF.add_application_dfsc#w'' 8677 7 7d' ' '4@AA A%(#'" r8cNt|jS)z#Get list of completions (AID names))rtrrr<s r6 get_app_nameszCardMF.get_app_namessD%,,..///r8r?ct|}||||S)r)rrrrfrprs r6rrzCardMF.get_selectablessAww&&u-- D,,U33444 r8c i}|gksd|vr6|d|jD|gksd|vr6|d|jD|S)zGet applications by AID + nameAIDSci|] }|j| Sr)rrs r6rz.CardMF.get_app_selectables..sFFFaFFFr8ANAMESc,i|]}|j |j|Srrrs r6rz.CardMF.get_app_selectables..s#IIIq!&IIIIr8)rfrr)r5rhris r6rpzCardMF.get_app_selectabless B;;&E// KKFF4+<+C+C+E+EFFF G G G B;;(e++ KKIID$5$<$<$>$>III K K K r8rycd|s|S|}|r||S|S)a\Decode the response to a SELECT command. This is the fall-back method which automatically defers to the standard decoding method defined by the card profile. When no profile is set, then no decoding is performed. Specific derived classes (usually ADF) can overload this method to install specific decoding. )r}r{)r5ryr+s r6r{zCardMF.decode_select_responsesC O""$$  11(;; ;Or8)rr0)rrrrr7r=rrrrrrprrobjectr{rrs@r6r_r_s77%%%000%'  4      )+tx}r8r_c\eZdZdZd dedeffd ZdZdefdZe d efd Z xZ S) r0z=ADF (Application Dedicated File) in the smart card filesystemFrhas_fsc tjdi|d|_||_||_|}|r||dSdS)Nr)rr7 applicationr2rrrWr)r5rrrrqrs r6r7zCardADF.__init__sw""6"""99;; [[]]  (  ! !$ ' ' ' ' ' ( (r8c2d|jr|jn|jzS)NzADF(%s)r'rr<s r6r=zCardADF.__str__s@DIIAAr8r>c0|jr |r|jS|jSr:rrAs r6rBzCardADF._path_elements" 9  9 8Or8rct|jtstd|jj||S)zb Export application specific parameters that are not part of the UICC filesystem. z.currently selected file is not of type CardADF)r/rr0rrrrs r6rzCardADF.export!sE %-w77 NLMM M".55guEEEr8r) rrrrrrr7r=rBrrrrs@r6r0r0 sGG((C(((((((BBB FFFF\FFFFFr8r0c@eZdZdZfdZfdZgfdeffd ZxZS)CardEFz,EF (Entry File) in the smart card filesystemc D||d<tjdi|dS)Nr%rrr7)r5r%rrs r6r7zCardEF.__init__.s/u ""6"""""r8cJdtzS)NzEF(%s)rrs r6r=zCardEF.__str__2rr8r?cht|}|gksd|vr=|fdjjD|gksd|vr=|fdjjD|S)rrdc:i|]}|j |k|j|Srrrrr5s r6rz*CardEF.get_selectables..Bs0```aAE`VW[_V_V_V_V_V_r8rec:i|]}|j |k|j|Srrrs r6rz*CardEF.get_selectables..Ds0bbbqQVbXY]aXaXaXaXaXar8)rrrrfr)rrrs` r6rrzCardEF.get_selectables5sww&&u-- B;;&E// KK````4;+?+F+F+H+H``` a a a B;;(e++ KKbbbbDK,@,G,G,I,Ibbb c c c r8) rrrrr7r=rrrrrs@r6rr+s66#####.....%'4r8rc *eZdZdZedGddeZ ddeded ed ed ed e f fd Z de de fdZ dede fdZddeedeefdZdde deede fdZdde deedefdZedefdZxZS) TransparentEFzTransparent EF (Entry File) in the smart card filesystem. A Transparent EF is a binary file with no formal structure. This is contrary to Record based EFs which have [fixed size] records that can be individually read/updated.zTransparent EF CommandscZeZdZdZejZedddedede j ed Z ejZ e d e d d e de de j e dZejZeddde j edZejZed e d d edede j edZejZedededde j edZdZdS)TransparentEF.ShellCommandsz,Shell commands specific for transparent EFs. --oneline store_true.No JSON pretty-printing, dump as a single lineactionhelpHEXSTR$Hex-string of encoded data to decodetyperc|jjj|j}|j||jdSzHDecode command-line provided hex-string as if it was read from the file.N)_cmdrr decode_hexr poutput_jsononeliner5optsdatas r6 do_decode_hexz)TransparentEF.ShellCommands.do_decode_hexWs@9?0;;DKHHD I " "4 6 6 6 6 6r8z--offsetrzByte offset for start of readrdefaultrz--lengthzNumber of bytes to readc|jj|j|j\}}|j|dS)z&Read binary data from a transparent EFN)rr read_binarylengthoffsetpoutputr5rr_sws r6do_read_binaryz*TransparentEF.ShellCommands.do_read_binarycsA)/55dk4;OOKT3 I  d # # # # #r8c|jj\}}|j||jdS)z(Read + decode data from a transparent EFN)rrread_binary_decrrr s r6do_read_binary_decodedz2TransparentEF.ShellCommands.do_read_binary_decodedms=)/99;;KT3 I " "4 6 6 6 6 6r8DATA Data bytes (hex format) to writec|jj|j|j\}}|r|j|dSdS)z'Update (Write) data of a transparent EFN)rr update_binaryrr r r s r6do_update_binaryz,TransparentEF.ShellCommands.do_update_binaryxsS)/77 4;OOKT3 ( !!$''''' ( (r8 --json-pathz1JSON path to modify specific element of file only$Abstract data (JSON format) to writercd|jrO|jj\}}t ||jt j|jnt j|j}|jj|\}}|r|j |dSdS)z0Encode + Update (Write) data of a transparent EFN) json_pathrrrrjsonloadsrupdate_binary_decrr5r data_jsonrrs r6do_update_binary_decodedz4TransparentEF.ShellCommands.do_update_binary_decodeds~ 2#'9?#B#B#D#D Cy$.#z$)446666!Jty11 )/;;IFFKT3 - &&t,,,,, - -r8c|jj\}}tjd5}d|z}t |d5}t j||dtdddn #1swxYwY|j |t |d5}t j |}dddn #1swxYwY||kr|j d n>|jj |\}}|r|j |ddddS#1swxYwYdS) z=Edit the JSON representation of the EF contents in an editor.pysim_prefix%s/filewrindentclsNr!Data not modified, skipping write)rrrtempfileTemporaryDirectoryopenrdumpr run_editorloadr rr) r5_opts orig_jsonrdirnamefilename text_file edited_jsonrs r6do_edit_binary_decodedz2TransparentEF.ShellCommands.do_edit_binary_decodeds #y>>@@ Y,H=== 5$w.(C((OIIi1+NNNNOOOOOOOOOOOOOOO $$X...(C((7I"&)I"6"6K777777777777777)++I%%&IJJJJ"&)/"C"CK"P"PKT35 ..t444 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5sZE A7+ E7A; ;E>A; ?-E,C  E C EC A"EE EN)rrrrargparseArgumentParserdec_hex_parser add_argumentrcmd2with_argparserrread_bin_parserrrread_bin_dec_parserrupd_bin_parserrupd_bin_dec_parserrr"r:rr8r6rrNs::0022##K )Y $ [ [ [##H9Ci#jjj  ^ , , 7 7 - , 7 2(133$$ [!:Y % [ [ [$$ [/H % J J J  _ - - $ $ . - $ 6h577((\.^ ) ` ` `  0 1 1 7 7 2 1 7 1022## [!:Y $ [ [ [##FAc#ddd  ^ , , ( ( - , ( 5X466'' C-` ( b b b''5['\\\  / 0 0 - - 1 0 - 5 5 5 5 5r8rNrVNr%r&r'r(r)sizec tjd|||||d|d|_d|_||_|g|_dSar Args: fid : File Identifier (4 hex digits) sfid : Short File Identifier (2 hex digits, optional) name : Brief name of the file, lik EF_ICCID desc : Description of the file parent : Parent CardFile object within filesystem hierarchy size : tuple of (minimum_size, recommended_size) r%r&r'r(r)Nr)rr7 _construct_tlvrFrr4 r5r%r&r'r(r)rFrrs r6r7zTransparentEF.__init__sb [St$T&[[TZ[[[  #11334r8 raw_bin_datar?ct|dd}t|r ||St|dd}t|r|t|S|jrt |j|S|jr]t j|jr|n|j}||| Sd| iS)aDecode raw (binary) data into abstract representation. A derived class would typically provide a _decode_bin() or _decode_hex() method for implementing this specifically for the given file. This function checks which of the method exists, add calls them (with conversion, as needed). Args: raw_bin_data : binary encoded data Returns: abstract_data; dict representing the decoded data _decode_binN _decode_hexraw) getattrcallablerrJrrKinspectisclassfrom_tlvto_dicthex)r5rMmethodts r6 decode_binzTransparentEF.decode_bins}d33 F   (6,'' '}d33 F   -6#l++,, , ? B"4?LAA A 9 &ty99H tyA JJ| $ $ $99;; |''))**r8 raw_hex_datact|dd}t|r ||St|}t|dd}t|r ||S|jrt |j|S|jr]t j|jr|n|j}||| Sd| iS)aDecode raw (hex string) data into abstract representation. A derived class would typically provide a _decode_bin() or _decode_hex() method for implementing this specifically for the given file. This function checks which of the method exists, add calls them (with conversion, as needed). Args: raw_hex_data : hex-encoded data Returns: abstract_data; dict representing the decoded data rPNrOrQ rRrSr rJrrKrTrUrVrWrXr5r\rYrMrZs r6rzTransparentEF.decode_hexs}d33 F   (6,'' '<(( }d33 F   (6,'' ' ? B"4?LAA A 9 &ty99H tyA JJ| $ $ $99;; |''))**r8 total_lenc||S|jdS|jd |jdS|jd |jdSdS)z'Get the size (total length) of the fileNrVr)rFr5r`s r6 __get_sizezTransparentEF.__get_sizesT    9 4 9Q< #9Q<  9Q< #9Q< tr8 abstract_dataclt|dd}t|r ||||St|dd}t|r-t||||S|jr+t |j|d||iS|jr]tj|jr|n|j}| || Std|z)a Encode abstract representation into raw (binary) data. A derived class would typically provide an _encode_bin() or _encode_hex() method for implementing this specifically for the given file. This function checks which of the method exists, add calls them (with conversion, as needed). Args: abstract_data : dict representing the decoded data total_len : expected total length of the encoded data (file size) Returns: binary encoded data _encode_binNr` _encode_hexr`0%s encoder not yet implemented. Patches welcome.) rRrS_TransparentEF__get_sizer rJrrKrTrU from_dictto_tlvNotImplementedErrorr5rdr`rYrZs r6 encode_binzTransparentEF.encode_bins1}d33 F   Q6-T__Y5O5OPPP P}d33 F   Vvvm9S9STTTUU U ? o"4?MKRVRaRabkRlRlCmnn n 9 &ty99H tyA KK & & &88:: ! > EGG Gr8c t|dd}t|r ||||St|dd}t|r/||||}t|S|jr8tt |j|d||iS|jrjtj|jr|n|j}| |t| Std|z)aEncode abstract representation into raw (hex string) data. A derived class would typically provide an _encode_bin() or _encode_hex() method for implementing this specifically for the given file. This function checks which of the method exists, add calls them (with conversion, as needed). Args: abstract_data : dict representing the decoded data total_len : expected total length of the encoded data (file size) Returns: hex string encoded data rhNrgrfr`ri) rRrSrjrrJrrKrTrUrkrlrm)r5rdr`rYrMrZs r6 encode_hexzTransparentEF.encode_hexsC}d33 F   Q6-T__Y5O5OPPP P}d33 F   %!6-T__Y=W=WXXXL|$$ $ ? rt TXTcTcdmTnTnGoppqq q 9 #&ty99H tyA KK & & &qxxzz?? "! > EGG Gr8rc|dkr$td|zd}|r<|}|dtj|dt zz }n/|}|dt|dzz }|S)z Export the file contents of a TransparentEF. This method returns a shell command string (See also ShellCommand definition in this class) that can be used to write the file contents back. transparentzTselected file has structure type '%s', expecting a file with structure 'transparent'zupdate_binary_decoded '%s' rr+zupdate_binary %s ) selected_file_structurer1rrdumpsrr rstrip)rr export_strresults r6rzTransparentEF.export6s  ( ( * *m ; ;s"::<<=>> >  B**,,F 9DJvayVa>>> ? ?r8c|jj|j\}}|j||jdS)z0Read + decode a record from a record-oriented EFN)rrread_record_decrrrr s r6do_read_record_decodedz/LinFixedEF.ShellCommands.do_read_record_decodedvsA)/99$.IIKT3 I " "4 6 6 6 6 6r8c:|jj}tdd|zD]h}|jj|\}}t |dkrt |}nd}|jd||fzidS)z*Read all records from a record-oriented EFrVrrrN)rrselected_file_num_of_recrQrrRrr )r5r4 num_of_recrrrrs r6do_read_recordsz(LinFixedEF.ShellCommands.do_read_records~sAACCJq!j.11 ? ?"io99%@@ st99q== YYFF&F !!)ufo"=>>>>  ? ?r8c |jj}g}tdd|zD]9}|jj|\}}||:|j||jdS)z3Read + decode all records from a record-oriented EFrVN)rrrrQrrHrr)r5rr data_listrrrs r6do_read_records_decodedz0LinFixedEF.ShellCommands.do_read_records_decodedsAACCJIq!j.11 ' '"io==eDD s  &&&& I " "9dl ; ; ; ; ;r8rrc|jj|j|j\}}|r|j|dSdS)z+Update (write) data to a record-oriented EFN)rr update_recordrrr r s r6do_update_recordz)LinFixedEF.ShellCommands.do_update_recordsS)/77 RRKT3 ( !!$''''' ( (r8rz3JSON path to modify specific element of record onlyrrrc||jrU|jj|j\}}t ||jt j|jnt j|j}|jj |j|\}}|r|j |dSdS)z4Encode + Update (write) data to a record-oriented EFN) rrrrrrrrrupdate_record_decr r s r6do_update_record_decodedz1LinFixedEF.ShellCommands.do_update_record_decodeds~ 2#'9?#B#B4>#R#R Cy$.#z$)446666!Jty11 )/;; ++KT3 ( !!$''''' ( (r8zNumber of record to be editedc|jj|j\}}t jd5}d|z}t |d5}tj||dtdddn #1swxYwY|j |t |d5}tj |}dddn #1swxYwY||kr|j d nD|jj |j|\}}|r|j|ddddS#1swxYwYdS) z8Edit the JSON representation of one record in an editor.r$r%r'r(rr)Nr,r-)rrrrr.r/r0rr1rr2r3r rr) r5rr5rr6r7r8r9rs r6do_edit_record_decodedz/LinFixedEF.ShellCommands.do_edit_record_decodeds $y>>t~NN Y,H=== 5$w.(C((OIIi1+NNNNOOOOOOOOOOOOOOO $$X...(C((7I"&)I"6"6K777777777777777)++I%%&IJJJJ"&)/"C"C #5#5KT35 ..t444 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5sZEA=1 E=B EB -E2C EC EC A(EEEN)rrrrr;r<r=r>rr?r@rread_rec_parserrrread_rec_dec_parserrread_recs_parserrread_recs_dec_parserrupd_rec_parserrupd_rec_dec_parserrredit_rec_dec_parserrrr8r6rrPs;;0022##K )Y $ [ [ [##H9Ci#jjj  ^ , , 7 7 - , 7 2(133$$ J8n % p p p$$ j/L % N N N  _ - - ? ? . - ?6h577((\.^ ) ` ` `(( j/L ) N N N  0 1 1 7 7 2 1 7 38244  - . . ? ? / . ? 7x688))+l/_ * a a a  1 2 2 < < 3 2 <1022## j/L $ N N N##FAc#ddd  ^ , , ( ( - , ( 5X466'' C-b ( d d d'' j/L ( N N N''5['\\\  / 0 0 ( ( 1 0 (6h577(( j/N ) P P P  0 1 1 5 5 2 1 5 5 5r8rNrEFr%r&r'r(r)rec_lenleftpadc tjd|||||d|||_||_|g|_d|_d|_dS)a Args: fid : File Identifier (4 hex digits) sfid : Short File Identifier (2 hex digits, optional) name : Brief name of the file, lik EF_ICCID desc : Description of the file parent : Parent CardFile object within filesystem hierarchy rec_len : Tuple of (minimum_length, recommended_length) leftpad: On write, data must be padded from the left to fit pysical record length rINr)rr7rrrr4rJrK) r5r%r&r'r(r)rrrrs r6r7zLinFixedEF.__init__sg [St$T&[[TZ[[[  #11334 r8rVr\ record_nrr?ct|dd}t|r |||St|}t|dd}t|r |||S|jrt |j|S|jr]t j|jr|n|j}||| Sd| iS)aDecode raw (hex string) data into abstract representation. A derived class would typically provide a _decode_record_bin() or _decode_record_hex() method for implementing this specifically for the given file. This function checks which of the method exists, add calls them (with conversion, as needed). Args: raw_hex_data : hex-encoded data record_nr : record number (1 for first record, ...) Returns: abstract_data; dict representing the decoded data _decode_record_hexNr_decode_record_binrQr^)r5r\rrYrMrZs r6rzLinFixedEF.decode_record_hexs3T:: F   =6,)<<< <<(( 3T:: F   =6,)<<< < ? B"4?LAA A 9 &ty99H tyA JJ| $ $ $99;; |''))**r8rMct|dd}t|r |||St|}t|dd}t|r |||S|jrt |j|S|jr]t j|jr|n|j}||| Sd|iS)aDecode raw (binary) data into abstract representation. A derived class would typically provide a _decode_record_bin() or _decode_record_hex() method for implementing this specifically for the given file. This function checks which of the method exists, add calls them (with conversion, as needed). Args: raw_bin_data : binary encoded data record_nr : record number (1 for first record, ...) Returns: abstract_data; dict representing the decoded data rNrrrQ) rRrSrrJrrKrTrUrVrW)r5rMrrYr\rZs r6decode_record_binzLinFixedEF.decode_record_bins3T:: F   =6,)<<< <<(( 3T:: F   =6,)<<< < ? B"4?LAA A 9 &ty99H tyA JJ| $ $ $99;; |$$r8r`c||S|jdS|jd |jdS|jd |jdSdS)0Get the length (total length) of the file recordNrVrrrbs r6 __get_rec_lenzLinFixedEF.__get_rec_lensT    < 4 <? &<? " <? &<? "tr8rdc t|dd}t|r!|||||St|dd}t|r0|||||}t|S|jr8tt |j|d||iS|jrjtj|jr|n|j}| |t| Std|z)aeEncode abstract representation into raw (hex string) data. A derived class would typically provide an _encode_record_bin() or _encode_record_hex() method for implementing this specifically for the given file. This function checks which of the method exists, add calls them (with conversion, as needed). Args: abstract_data : dict representing the decoded data record_nr : record number (1 for first record, ...) total_len : expected total length of the encoded data (record length) Returns: hex string encoded data _encode_record_hexNrr`_encode_record_binr`ri) rRrS_LinFixedEF__get_rec_lenrrJrrKrTrUrkrlrm)r5rdrr`rYrMrZs r6encode_record_hexzLinFixedEF.encode_record_hex1sP3T:: F   i6-9$J\J\]fJgJghhh h3T:: F   %!6-9RVRdRdenRoRopppL|$$ $ ? ut TXTfTfgpTqTqGrsstt t 9 #&ty99H tyA KK & & &qxxzz?? "! > EGG Gr8c pt|dd}t|r!|||||St|dd}t|r.t|||||S|jr+t |j|d||iS|jr]tj|jr|n|j}| || Std|z)a]Encode abstract representation into raw (binary) data. A derived class would typically provide an _encode_record_bin() or _encode_record_hex() method for implementing this specifically for the given file. This function checks which of the method exists, add calls them (with conversion, as needed). Args: abstract_data : dict representing the decoded data record_nr : record number (1 for first record, ...) total_len : expected total length of the encoded data (record length) Returns: binary encoded data rNrrr`ri) rRrSrr rJrrKrTrUrkrlrm)r5rdrr`rYrZs r6encode_record_binzLinFixedEF.encode_record_binOs=3T:: F   i6-9$J\J\]fJgJghhh h3T:: F   nvvmydN`N`ajNkNklllmm m ? p"4?MKPTPbPbclPmPmCnoo o 9 &ty99H tyA KK & & &88:: ! > EGG Gr8rcb|dkr<|dkr$td|zd}|}|rtd|dzD]u}|r?||}|d|t j|dtfzz }C||}|d |t|dfzz }vnd} |r?||}|d|t j|dtfzz }n2||}|d |t|dfzz }|#t$r}|j d krYd }~nYd }~nd }~wwxYw|dz}| S) z Export the file contents of a LinFixedEF (or a CyclicEF). This method returns a shell command string (See also ShellCommand definition in this class) that can be used to write the file contents back. linear_fixedcycliczaselected file has structure type '%s', expecting a file with structure 'linear_fixed' or 'cyclic'rtrVzupdate_record_decoded %d '%s' rruzupdate_record %d %s T9402N) rvr1rrQrrrwrrrr sw_actualrx)rrryrr,rzes r6rzLinFixedEF.exportls&  ( ( * *n < <A^A^A`A`dlAlAlA"::<<=>> > 3355  1j1n-- R RR"22155F#D4:V\]^V_epKqKqKqGr#rsJJ"..q11F#:aVAY=P#PQJJ  RA  V!&!6!6q!9!9"'HAtzZ`abZcitOuOuOuKv'vw !&!2!21!5!5"'>!SPQ^^AT'TU G ${f,,-,,,,E "!!!s;A3E00 F: FF)NNNNrEF)rVr:)rrrrr r rrrr*r|rr7rrrr}rrrrrrrrs@r6rrJs?? 566@5@5@5@5@5 @5@576@5DRV]bCs3!&);?VZ&++c+c+$++++8%i%C%D%%%%8x} &GGtGGPXY\P]GilGGGG<GGtGGQYZ]Q^GjsGGGG:-"-"-"-"\-"-"-"-"-"r8rc BeZdZdZ d dededededed ef fd ZxZS) CyclicEFz3Cyclic EF (Entry File) in the smart card filesystemNrEr%r&r'r(r)rc Htjd||||||d|dS)N)r%r&r'r(r)rrr) r5r%r&r'r(r)rrrs r6r7zCyclicEF.__init__s7lSt$T&Zalleklllllr8r{) rrrrrr*r|r7rrs@r6rrs==im!*mmCmsmm3m_emmmmmmmmmmmr8rceZdZdZ ddededededed eed effd Z d ed e fdZ de d e fdZ ddeed eefdZdde deed efdZdde deed e fdZde fdZd efdZxZS) TransRecEFaTransparent EF (Entry File) containing fixed-size records. These are the real odd-balls and mostly look like mistakes in the specification: Specified as 'transparent' EF, but actually containing several fixed-length records inside. We add a special class for those, so the user only has to provide encoder/decoder functions for a record, while this class takes care of split / merge of records. NrEr%rr&r'r(r)rFc Vtjd||||||d|||_dS)a Args: fid : File Identifier (4 hex digits) sfid : Short File Identifier (2 hex digits, optional) name : Brief name of the file, like EF_ICCID desc : Description of the file parent : Parent CardFile object within filesystem hierarchy rec_len : Length of the fixed-length records within transparent EF size : tuple of (minimum_size, recommended_size) )r%r&r'r(r)rFNr)rr7r) r5r%rr&r'r(r)rFrrs r6r7zTransRecEF.__init__s> fSt$T&W[ff_efff r8r\r?c,t|dz|krd|iSt|dd}t|r ||St |}t|dd}t|r ||S|jrt |j|S|jr]tj |jr|n|j}| || Sd|iS)aDecode raw (hex string) data into abstract representation. A derived class would typically provide a _decode_record_bin() or _decode_record_hex() method for implementing this specifically for the given file. This function checks which of the method exists, add calls them (with conversion, as needed). Args: raw_hex_data : hex-encoded data Returns: abstract_data; dict representing the decoded data rQrNr) rR_TransRecEF__get_rec_lenrRrSr rJrrKrTrUrVrWr_s r6rzTransRecEF.decode_record_hexs |   !D$6$6$8$8 8 8<( (3T:: F   (6,'' '<(( 3T:: F   (6,'' ' ? B"4?LAA A 9 &ty99H tyA JJ| $ $ $99;; |$$r8rMc@t||krdt|iSt|dd}t |r ||St|}t|dd}t |r ||S|jrt |j|S|jr]tj |jr|n|j}| || Sd|iS)aDecode raw (binary) data into abstract representation. A derived class would typically provide a _decode_record_bin() or _decode_record_hex() method for implementing this specifically for the given file. This function checks which of the method exists, add calls them (with conversion, as needed). Args: raw_bin_data : binary encoded data Returns: abstract_data; dict representing the decoded data rQrNr) rRrrrRrSrJrrKrTrUrVrW)r5rMrYr\rZs r6rzTransRecEF.decode_record_bins |  t1133 3 33|,,- -3T:: F   (6,'' '<(( 3T:: F   (6,'' ' ? B"4?LAA A 9 &ty99H tyA JJ| $ $ $99;; |$$r8r`c*||S|jr|jSdS)rNrrbs r6rzTransRecEF.__get_rec_lens)    < < tr8rdc t|dd}t|r ||||St|dd}t|r-t||||S|jrEtt t |j|d||iS|jrjtj |jr|n|j}| |t| Std|z)a%Encode abstract representation into raw (hex string) data. A derived class would typically provide an _encode_record_bin() or _encode_record_hex() method for implementing this specifically for the given file. This function checks which of the method exists, add calls them (with conversion, as needed). Args: abstract_data : dict representing the decoded data total_len : expected total length of the encoded data (record length) Returns: hex string encoded data rNrgrr`ri) rRrSrrrJrrrKrTrUrkrlrmrns r6rzTransRecEF.encode_record_hexsb3T:: F   T6-T5G5G 5R5RSSS S3T:: F   Yvvm9K9KI9V9VWWWXX X ? b{?4?M4?@R@RS\@]@]3^$`$`aabb b 9 #&ty99H tyA KK & & &qxxzz?? "! > EGG Gr8c t|dd}t|r ||||St|dd}t|r-t||||S|jr8t t |j|d||iS|jr]tj |jr|n|j}| || Std|z)aEncode abstract representation into raw (binary) data. A derived class would typically provide an _encode_record_bin() or _encode_record_hex() method for implementing this specifically for the given file. This function checks which of the method exists, add calls them (with conversion, as needed). Args: abstract_data : dict representing the decoded data total_len : expected total length of the encoded data (record length) Returns: binary encoded data rNrgrr`ri) rRrSrr rJrrrKrTrUrkrlrmrns r6rzTransRecEF.encode_record_bin+sM3T:: F   T6-T5G5G 5R5RSSS S3T:: F   Yvvm9K9KI9V9VWWWXX X ? ]t 0;D EGG Gr8cfdtdtjD}fd|DS)Nc4g|]}||jzSrr)rrTrMr5s r6 z*TransRecEF._decode_bin..Is?FFFq4</0FFFr8rc:g|]}|Sr)rrs r6rz*TransRecEF._decode_bin..Ks':::a&&q)):::r8)rQrRr)r5rMchunkss`` r6rOzTransRecEF._decode_binHsiFFFFF C $5$5t|DDFFF::::6::::r8c Nfd|D}d|S)Nc fg|]-}|dd.S)r`Nrg)rget)rrrr5s r6rz*TransRecEF._encode_bin..Ns<nnn[\$(( ;PT8U8U(VVnnnr8r8)rD)r5rdrrs` ` r6rfzTransRecEF._encode_binMs3nnnnn`mnnnxxr8r{r:)rrrrrrrr*r|r7rrr}rrrrrObytesrfrrs@r6rrs`d?H  C # S s Y\ !&) 8<       %c %d % % % %D%i%D%%%%@  x}     GGtG GY\GGGG:GGtG GYbGGGG:; ;;;;  e        r8rc eZdZdZedGddeZ ddeded ed ed ed e f fd Z e de fdZ xZS)BerTlvEFaVBER-TLV EF (Entry File) in the smart card filesystem. A BER-TLV EF is a binary file with a BER (Basic Encoding Rules) TLV structure NOTE: We currently don't really support those, this class is simply a wrapper around TransparentEF as a place-holder, so we can already define EFs of BER-TLV type without fully supporting them.zBER-TLV EF CommandsceZdZdZejZedede j edZ dZ ejZ e dede ded e j e d ZejZedede j ed Zd Zd S)BerTlvEF.ShellCommandsz(Shell commands specific for BER-TLV EFs.TAGz BER-TLV Tag of value to retrieverc|jj|j\}}|j|dS)z&Retrieve (Read) data from a BER-TLV EFN)rr retrieve_datarr r s r6do_retrieve_dataz'BerTlvEF.ShellCommands.do_retrieve_datacs=)/77AAKT3 I  d # # # # #r8cv|jj}|j|dS)z)List tags available in a given BER-TLV EFN)rr retrieve_tagsr )r5r4tagss r6do_retrieve_tagsz'BerTlvEF.ShellCommands.do_retrieve_tagsis39?0022D I  d # # # # #r8zBER-TLV Tag of value to setrrc|jj|j|j\}}|r|j|dSdS)z0Set (Write) data for a given tag in a BER-TLV EFN)rrset_datarrr r s r6 do_set_dataz"BerTlvEF.ShellCommands.do_set_datassS)/2248TYGGKT3 ( !!$''''' ( (r8c|jj|jd\}}|r|j|dSdS)z+Delete data for a given tag in a BER-TLV EFN)rrrrr r s r6do_delete_dataz%BerTlvEF.ShellCommands.do_delete_data~sQ)/2248TBBKT3 ( !!$''''' ( (r8c|jj}|D]"}|jj|d#dS)z!Delete all data from a BER-TLV EFN)rrrr)r5rrtags r6 do_delete_allz$BerTlvEF.ShellCommands.do_delete_allsM9?0022D 4 4 ((d3333 4 4r8N)rrrrr;r<retrieve_data_parserr>rr?r@rrset_data_parserrrdel_data_parserrrrr8r6rr[s{666x688)) 'I * K K K  1 2 2 $ $ 3 2 $  $ $ $ 2(133$$ 'D % F F F$$V)Bd$eee  _ - - ( ( . - ( 2(133$$ 'D % F F F  _ - - ( ( . - (  4 4 4 4 4r8rNrEr%r&r'r(r)rFc tjd|||||d|d|_||_|g|_dSrH)rr7rJrFrr4rLs r6r7zBerTlvEF.__init__s[ [St$T&[[TZ[[[ #11334r8rc|dkr$td|z|rtdd}|}|gkr|dz }n]|dz }|D]U}||}t t |d\}}}} |d|t|fzz }V|S) z Export the file contents of a BerTlvEF. This method returns a shell command string (See also ShellCommand definition in this class) that can be used to write the file contents back. ber_tlvzPselected file has structure type '%s', expecting a file with structure 'ber_tlv'z6BerTlvEF encoder not yet implemented. Patches welcome.rtz# empty file, no tagsz delete_all rzset_data 0x%02x %s ) rvr1rmrrrr rrx) rrryrrZrzrlvalremainers r6rzBerTlvEF.exports  ( ( * *i 7 7o"::<<=>> >  `%&^__ _ ""$$ 2:: 1 1JJ . (J G G,,Q//*:3vay>>*J*J'ah5CHH EF !!!r8r{)rrrrr r rrr*r|r7rrrrrs@r6rrSs++011-4-4-4-4-4 -4-421-4^im'55C5s5535_e5555555 """"\"""""r8rsw_dataswc|D]G\}}||vr |||fcS|D]\}}t||r||fccSHdS)zInterpret a given status word. Args: sw_data : Hierarchical dict of status word matches sw : status word to match (string of 4 hex digits) Returns: tuple of two strings (class_string, description) N)itemsr)rr class_strswdictpatterndescrs r6 interpret_swrs%]]__** 6 <<vbz* * * *$llnn * *NGUG$$ *!5)))))) * * 4r8c\eZdZdZd deededefdZdZ dZ e d e fd Z dS) CardApplicationzqA card application is represented by an ADF (with contained hierarchy) and optionally some SW definitions.Nadfrrc|r|}||_||_|pi|_|jr!|p |jj|_||j_dS||_dS)zc Args: adf : ADF name sw : Dict of status word conversions N)r2r'rrrr)r5r'rrrs r6r7zCardApplication.__init__sg  ))++C ( 8 *dhlDH#'DH DHHHr8cd|jzS)NzAPP(%s)rr<s r6r=zCardApplication.__str__sDI&&r8c,t|j|S)zInterpret a given status word within the application. Args: sw : Status word as string of 4 hex digits Returns: Tuple of two strings )rr)r5rs r6rzCardApplication.interpret_swsDGR(((r8rc0dt|jzS)z Export application specific parameters, in the form of commandline script. (see also comment in the export method of class "CardFile") z# %s has no exportable featuresrrs r6rzCardApplication.exports 13u7J3K3KKKr8)NNN)rrrrrr0rrr7r=rrrrrr8r6rrs(7"3QU$''' ) ) )LLLL\LLLr8rceZdZdZgZeejd dZede de fdZ e de ddfdZ d S) CardModelzA specific card model, typically having some additional vendor-specific files. All you need to do is to define a sub-class with a list of ATRs or an overridden match method.rs RuntimeStatecdS)z/Add model specific files to given RuntimeState.Nr)r+rs r6rzCardModel.add_filessr8sccr?c"|}|jD] }||krtd|jdS!t |d}|jD]5}t |d}||krtd|jdS6dS)z&Test if given card matches this model.zDetected CardModel:ThbF)get_atr_atrsprintrr)r+r card_atratr card_atr_hbatr_hbs r6matchzCardModel.matchs;;==9  Ch+S\:::tt#8,,T2 9  C!#&&t,F$$+S\:::tt%ur8ctD],}||r||-dS)zCheck if any of the CardModel sub-classes 'match' the currently inserted card (by ATR or overriding the 'match' method). If so, call their 'add_files' method.N)r__subclasses__rr)r rms r6apply_matching_modelszCardModel.apply_matching_modelssK ))++  Awws||  B  r8N)rr)rrrrr classmethodabcabstractmethodrrrrrrrr8r6rrs E>>>[>D[  ?    \   r8rceZdZdZdeeeeeeffdZdefdZ defdZ ddde fdZ d Z d Zd Zdd Zddde fd ZdS)Pathz%Representation of a file-system path.pct|tr|d}n6t|r't|dtr d|D}d|D|_dS)Nr"rcg|]}d|zS)z%04xrrs r6rz!Path.__init__..&s'''!'''r8c6g|]}|Sr)upperrs r6rz!Path.__init__..(s ***1QWWYY***r8)r/rsplitrRrrt)r5rs r6r7z Path.__init__!st a   ( AA VV ( 1Q4-- (''Q'''A***** r8r?c6d|jS)Nr")rDrtr<s r6r=z Path.__str__*sxx """r8c&dt|zS)NzPath(%s))rr<s r6__repr__z Path.__repr__-sSYY''r8otherc"|j|jkSr:rtr5r's r6__eq__z Path.__eq__0syEJ&&r8c|j|Sr:r))r5rTs r6 __getitem__zPath.__getitem__3sy|r8c*t|jSr:rRrtr<s r6__len__z Path.__len__6s49~~r8ct|tr |j|z}n0t|tr|j|jz}n |j|gz}t|Sr:)r/rtr)r5ars r6__add__z Path.__add__9s[ a    A AA 4   AF"AA QCAAwwr8ct|jr+|jddvrt|jddS|S)z?Return a path relative to MF, i.e. without initial explicit MF.r)r#3F00rVN)rRrtrr<s r6relative_to_mfzPath.relative_to_mfBs? ty>> 'diln<< !"" && & r8ct|jt|jkrdS|jdt|j|jkrdSdS)z6Is this instance a parent of the given other instance?FNTr/r*s r6 is_parentzPath.is_parentHsL ty>>S__ , ,5 :os49~~o &$) 3 34ur8N)r?r)rrrrr rrrr7r=r&rr+r-r0r3r6r8rr8r6rrs//+%T#YS 9:++++#####(#(((('F't'''' v$r8r)?rtypingrrrrrrr r;r.rrrTr?r r smartcard.utilr osmocom.utilsr rrrrrrr osmocom.tlvrosmocom.constructrrr pySim.utilsrrpySim.jsonpathrpySim.commandsrpySim.exceptionsrrrr|rr*r_r0rrrrrrrrrrABCrrrr8r6rCs@2FEEEEEEEEEEEEEEEEE  22222222""""""eeeeeeeeeeeeeeeeeeee((((((KKKKKKKKKK........))))))******)))))) T#Yc3h78 S(3-  ALALALALALALALALHEEEEEXEEEPFFFFFVFFFRFFFFFfFFF@X:"""""F"""DP"P"P"P"P"P"P"P"f mmmmmzmmmj j j j j j j j Za"a"a"a"a"va"a"a"H$C(*L*L*L*L*L*L*L*L\# # # # # # # # L//////////r8