aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHarald Welte <laforge@osmocom.org>2022-02-12 21:41:59 +0100
committerHarald Welte <laforge@osmocom.org>2022-02-15 15:35:35 +0100
commitaceb2a548a9ca9e892bcaa40a531014d89b2e3e0 (patch)
tree49a0ee7abdc87417efe8d73c77a9fde05ac778da
parent419bb496e1f23ac2073eb3b91fbc30a7be612910 (diff)
ust_service_check: proper treatment of files in sub-directories
We must not only consider files in the current directory (ADF.USIM) but also in its sub-directories. This requires us to be able to determine the path we need to traverse between the currently selected file (EF.UST) and the respective file in some other directory, which is implemented via CardFile.build_select_path_to(). Change-Id: I61797fefa9dafa36a8a62c11aa2cfaeecb015740
-rw-r--r--pySim/filesystem.py78
-rw-r--r--pySim/ts_31_102.py8
2 files changed, 71 insertions, 15 deletions
diff --git a/pySim/filesystem.py b/pySim/filesystem.py
index dd80071..d1c3e1f 100644
--- a/pySim/filesystem.py
+++ b/pySim/filesystem.py
@@ -115,6 +115,34 @@ class CardFile(object):
ret.append(elem)
return ret
+ def fully_qualified_path_fobj(self) -> List['CardFile']:
+ """Return fully qualified path to file as list of CardFile instance references."""
+ if self.parent and self.parent != self:
+ ret = self.parent.fully_qualified_path_fobj()
+ else:
+ ret = []
+ if self:
+ ret.append(self)
+ return ret
+
+ def build_select_path_to(self, target: 'CardFile') -> Optional[List['CardFile']]:
+ """Build the relative sequence of files we need to traverse to get from us to 'target'."""
+ cur_fqpath = self.fully_qualified_path_fobj()
+ target_fqpath = target.fully_qualified_path_fobj()
+ inter_path = []
+ cur_fqpath.pop() # drop last element (currently selected file, doesn't need re-selection
+ cur_fqpath.reverse()
+ for ce in cur_fqpath:
+ inter_path.append(ce)
+ for i in range(0, len(target_fqpath)-1):
+ te = target_fqpath[i]
+ if te == ce:
+ for te2 in target_fqpath[i+1:]:
+ inter_path.append(te2)
+ # we found our common ancestor
+ return inter_path
+ return None
+
def get_mf(self) -> Optional['CardMF']:
"""Return the MF (root) of the file system."""
if self.parent == None:
@@ -1337,6 +1365,45 @@ class RuntimeState(object):
self.selected_file = f
return select_resp
+ def _select_pre(self, cmd_app):
+ # unregister commands of old file
+ if cmd_app and self.selected_file.shell_commands:
+ for c in self.selected_file.shell_commands:
+ cmd_app.unregister_command_set(c)
+
+ def _select_post(self, cmd_app):
+ # register commands of new file
+ if cmd_app and self.selected_file.shell_commands:
+ for c in self.selected_file.shell_commands:
+ cmd_app.register_command_set(c)
+
+ def select_file(self, file: CardFile, cmd_app=None):
+ """Select a file (EF, DF, ADF, MF, ...).
+
+ Args:
+ file : CardFile [or derived class] instance
+ cmd_app : Command Application State (for unregistering old file commands)
+ """
+ # we need to find a path from our self.selected_file to the destination
+ inter_path = self.selected_file.build_select_path_to(file)
+ if not inter_path:
+ raise RuntimeError('Cannot determine path from %s to %s' % (self.selected_file, file))
+
+ self._select_pre(cmd_app)
+
+ for p in inter_path:
+ try:
+ if isinstance(p, CardADF):
+ (data, sw) = self.card.select_adf_by_aid(p.aid)
+ else:
+ (data, sw) = self.card._scc.select_file(p.fid)
+ self.selected_file = p
+ except SwMatchError as swm:
+ self._select_post(cmd_app)
+ raise(swm)
+
+ self._select_post(cmd_app)
+
def select(self, name: str, cmd_app=None):
"""Select a file (EF, DF, ADF, MF, ...).
@@ -1348,10 +1415,7 @@ class RuntimeState(object):
if is_hex(name):
name = name.lower()
- # unregister commands of old file
- if cmd_app and self.selected_file.shell_commands:
- for c in self.selected_file.shell_commands:
- cmd_app.unregister_command_set(c)
+ self._select_pre(cmd_app)
if name in sels:
f = sels[name]
@@ -1372,11 +1436,7 @@ class RuntimeState(object):
# store the decoded FCP for later reference
self.selected_file_fcp = select_resp
- # register commands of new file
- if cmd_app and self.selected_file.shell_commands:
- for c in self.selected_file.shell_commands:
- cmd_app.register_command_set(c)
-
+ self._select_post(cmd_app)
return select_resp
def status(self):
diff --git a/pySim/ts_31_102.py b/pySim/ts_31_102.py
index 447ef95..7d0eb28 100644
--- a/pySim/ts_31_102.py
+++ b/pySim/ts_31_102.py
@@ -608,12 +608,8 @@ class EF_UServiceTable(TransparentEF):
for f in files_by_service[s]:
should_exist = f.should_exist_for_services(active_services)
try:
- (data, sw) = cmd.card._scc.select_file(f.fid)
+ cmd.rs.select_file(f)
exists = True
- fcp = f.decode_select_response(data)
- # if we just selected a directory, go back
- if fcp['file_descriptor']['file_type'] == 'df':
- cmd.card._scc.select_parent_df()
except SwMatchError as e:
sw = str(e)
exists = False
@@ -625,7 +621,7 @@ class EF_UServiceTable(TransparentEF):
cmd.perror(" ERROR: File %s is not selectable (%s) but should!" % (f, sw))
finally:
# re-select the EF.UST
- cmd.card._scc.select_file(self.fid)
+ cmd.rs.select_file(self)
return num_problems
class EF_UST(EF_UServiceTable):