Fix various mistakes around the CardADF <-> CardApplication dualism

When the CardFile hierarchy talks about 'application' it means CardADF.

When the RuntimeState and CardProfile talk about 'application' they mean
a CardApplication.

Let's clarify this in the file names, and make CardADF have an optional
reference to the CardApplication, so that application specific status
word interpretation really works.

Change-Id: Ibc80a41d79dca547f14d5d84f447742e6b46d7ca
This commit is contained in:
Harald Welte 2021-04-02 20:27:05 +02:00
parent 1e45657e0f
commit 5ce3524f5f
2 changed files with 26 additions and 17 deletions

View File

@ -45,8 +45,8 @@ from pySim.card_handler import card_handler
from pySim.filesystem import CardMF, RuntimeState, CardDF, CardADF from pySim.filesystem import CardMF, RuntimeState, CardDF, CardADF
from pySim.ts_51_011 import CardProfileSIM, DF_TELECOM, DF_GSM from pySim.ts_51_011 import CardProfileSIM, DF_TELECOM, DF_GSM
from pySim.ts_102_221 import CardProfileUICC from pySim.ts_102_221 import CardProfileUICC
from pySim.ts_31_102 import ADF_USIM from pySim.ts_31_102 import CardApplicationUSIM
from pySim.ts_31_103 import ADF_ISIM from pySim.ts_31_103 import CardApplicationISIM
from pySim.card_data import CardDataCsv, card_data_register, card_data_get_field from pySim.card_data import CardDataCsv, card_data_register, card_data_get_field
@ -441,8 +441,8 @@ if __name__ == '__main__':
sys.exit(2) sys.exit(2)
profile = CardProfileUICC() profile = CardProfileUICC()
profile.add_application(ADF_USIM()) profile.add_application(CardApplicationUSIM)
profile.add_application(ADF_ISIM()) profile.add_application(CardApplicationISIM)
rs = RuntimeState(card, profile) rs = RuntimeState(card, profile)

View File

@ -284,8 +284,8 @@ class CardMF(CardDF):
def __str__(self): def __str__(self):
return "MF(%s)" % (self.fid) return "MF(%s)" % (self.fid)
def add_application(self, app:'CardADF'): def add_application_df(self, app:'CardADF'):
"""Add an ADF (Application Dedicated File) to the MF""" """Add an Application to the MF"""
if not isinstance(app, CardADF): if not isinstance(app, CardADF):
raise TypeError("Expected an ADF instance") raise TypeError("Expected an ADF instance")
if app.aid in self.applications: if app.aid in self.applications:
@ -334,10 +334,12 @@ class CardADF(CardDF):
"""ADF (Application Dedicated File) in the smart card filesystem""" """ADF (Application Dedicated File) in the smart card filesystem"""
def __init__(self, aid:str, **kwargs): def __init__(self, aid:str, **kwargs):
super().__init__(**kwargs) super().__init__(**kwargs)
# reference to CardApplication may be set from CardApplication constructor
self.application:Optional[CardApplication] = None
self.aid = aid # Application Identifier self.aid = aid # Application Identifier
mf = self.get_mf() mf = self.get_mf()
if mf: if mf:
mf.add_application(self) mf.add_application_df(self)
def __str__(self): def __str__(self):
return "ADF(%s)" % (self.aid) return "ADF(%s)" % (self.aid)
@ -807,12 +809,13 @@ class RuntimeState(object):
""" """
self.mf = CardMF() self.mf = CardMF()
self.card = card self.card = card
self.selected_file = self.mf self.selected_file:CardDF = self.mf
self.profile = profile self.profile = profile
# add applications + MF-files from profile # add application ADFs + MF-files from profile
apps = self._match_applications() apps = self._match_applications()
for a in apps: for a in apps:
self.mf.add_application(a) if a.adf:
self.mf.add_application_df(a.adf)
for f in self.profile.files_in_mf: for f in self.profile.files_in_mf:
self.mf.add_file(f) self.mf.add_file(f)
self.conserve_write = True self.conserve_write = True
@ -849,8 +852,8 @@ class RuntimeState(object):
else: else:
return self.selected_file.parent return self.selected_file.parent
def get_application(self) -> Optional[CardADF]: def get_application_df(self) -> Optional[CardADF]:
"""Obtain the currently selected application (if any). """Obtain the currently selected application DF (if any).
Returns: Returns:
CardADF() instance or None""" CardADF() instance or None"""
@ -872,16 +875,16 @@ class RuntimeState(object):
Returns: Returns:
Tuple of two strings Tuple of two strings
""" """
app = self.get_application() adf = self.get_application_df()
if app: if adf:
app = adf.application
# The application either comes with its own interpret_sw # The application either comes with its own interpret_sw
# method or we will use the interpret_sw method from the # method or we will use the interpret_sw method from the
# card profile. # card profile.
if hasattr(app, "interpret_sw"): if app and hasattr(app, "interpret_sw"):
return app.interpret_sw(sw) return app.interpret_sw(sw)
else: else:
return self.profile.interpret_sw(sw) return self.profile.interpret_sw(sw)
return app.interpret_sw(sw)
else: else:
return self.profile.interpret_sw(sw) return self.profile.interpret_sw(sw)
@ -1078,7 +1081,7 @@ def interpret_sw(sw_data:dict, sw:str):
class CardApplication(object): class CardApplication(object):
"""A card application is represented by an ADF (with contained hierarchy) and optionally """A card application is represented by an ADF (with contained hierarchy) and optionally
some SW definitions.""" some SW definitions."""
def __init__(self, name, adf:str=None, sw:dict=None): def __init__(self, name, adf:Optional[CardADF]=None, aid:str=None, sw:dict=None):
""" """
Args: Args:
adf : ADF name adf : ADF name
@ -1087,6 +1090,12 @@ class CardApplication(object):
self.name = name self.name = name
self.adf = adf self.adf = adf
self.sw = sw or dict() self.sw = sw or dict()
# back-reference from ADF to Applicaiton
if self.adf:
self.aid = aid or self.adf.aid
self.adf.application = self
else:
self.aid = aid
def __str__(self): def __str__(self):
return "APP(%s)" % (self.name) return "APP(%s)" % (self.name)