aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-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):