dexter has uploaded this change for review. (
https://gerrit.osmocom.org/c/pysim/+/37612?usp=email )
Change subject: pySim-shell: move export code into filesystem class model
......................................................................
pySim-shell: move export code into filesystem class model
The code that generates the filesystem export lines for the various
different file structures can be moved into the filesystem class model.
This simplifies the code since we do not need any extra logic to
distinguish between the different file structures.
Related: OS#6092
Change-Id: Icc2ee60cfc4379411744ca1033d79a1ee9cff5a6
---
M pySim-shell.py
M pySim/filesystem.py
2 files changed, 118 insertions(+), 58 deletions(-)
git pull ssh://gerrit.osmocom.org:29418/pysim refs/changes/12/37612/1
diff --git a/pySim-shell.py b/pySim-shell.py
index 0e7e63c..4f5959b 100755
--- a/pySim-shell.py
+++ b/pySim-shell.py
@@ -599,66 +599,14 @@
self._cmd.poutput("# directory: %s (%s)" % (df_path, df_path_fid))
try:
fcp_dec = self._cmd.lchan.select(filename, self._cmd)
- self._cmd.poutput("# file: %s (%s)" % (
- self._cmd.lchan.selected_file.name, self._cmd.lchan.selected_file.fid))
-
- structure = self._cmd.lchan.selected_file_structure()
- self._cmd.poutput("# structure: %s" % str(structure))
+ self._cmd.poutput("# file: %s (%s)" %
+ (self._cmd.lchan.selected_file.name,
self._cmd.lchan.selected_file.fid))
+ self._cmd.poutput("# structure: %s" %
self._cmd.lchan.selected_file_structure())
self._cmd.poutput("# RAW FCP Template: %s" %
str(self._cmd.lchan.selected_file_fcp_hex))
self._cmd.poutput("# Decoded FCP Template: %s" %
str(self._cmd.lchan.selected_file_fcp))
+ self._cmd.poutput("select " +
self._cmd.lchan.selected_file.fully_qualified_path_str())
+ self._cmd.poutput(self._cmd.lchan.selected_file.export(as_json,
self._cmd.lchan))
- for f in df_path_list:
- self._cmd.poutput("select " + str(f))
- self._cmd.poutput("select " + self._cmd.lchan.selected_file.name)
-
- if structure == 'transparent':
- if as_json:
- result = self._cmd.lchan.read_binary_dec()
- self._cmd.poutput("update_binary_decoded '%s'" %
json.dumps(result[0], cls=JsonEncoder))
- else:
- result = self._cmd.lchan.read_binary()
- self._cmd.poutput("update_binary " + str(result[0]))
- elif structure == 'cyclic' or structure == 'linear_fixed':
- # Use number of records specified in select response
- num_of_rec = self._cmd.lchan.selected_file_num_of_rec()
- if num_of_rec:
- for r in range(1, num_of_rec + 1):
- if as_json:
- result = self._cmd.lchan.read_record_dec(r)
- self._cmd.poutput("update_record_decoded %d
'%s'" % (r, json.dumps(result[0], cls=JsonEncoder)))
- else:
- result = self._cmd.lchan.read_record(r)
- self._cmd.poutput("update_record %d %s" % (r,
str(result[0])))
-
- # When the select response does not return the number of records, read
until we hit the
- # first record that cannot be read.
- else:
- r = 1
- while True:
- try:
- if as_json:
- result = self._cmd.lchan.read_record_dec(r)
- self._cmd.poutput("update_record_decoded %d
'%s'" % (r, json.dumps(result[0], cls=JsonEncoder)))
- else:
- result = self._cmd.lchan.read_record(r)
- self._cmd.poutput("update_record %d %s" % (r,
str(result[0])))
- except SwMatchError as e:
- # We are past the last valid record - stop
- if e.sw_actual == "9402":
- break
- # Some other problem occurred
- else:
- raise e
- r = r + 1
- elif structure == 'ber_tlv':
- tags = self._cmd.lchan.retrieve_tags()
- for t in tags:
- result = self._cmd.lchan.retrieve_data(t)
- (tag, l, val, remainer) = bertlv_parse_one(h2b(result[0]))
- self._cmd.poutput("set_data 0x%02x %s" % (t, b2h(val)))
- else:
- raise RuntimeError(
- 'Unsupported structure "%s" of file "%s"'
% (structure, filename))
except Exception as e:
bad_file_str = df_path + "/" + str(filename) + ", " +
str(e)
self._cmd.poutput("# bad file: %s" % bad_file_str)
diff --git a/pySim/filesystem.py b/pySim/filesystem.py
index 77482cc..ad124ff 100644
--- a/pySim/filesystem.py
+++ b/pySim/filesystem.py
@@ -35,7 +35,9 @@
from cmd2 import CommandSet, with_default_category
from smartcard.util import toBytes
-from pySim.utils import sw_match, h2b, b2h, is_hex, auto_int, auto_uint8, auto_uint16,
is_hexstr
+from pySim.utils import sw_match, h2b, b2h, is_hex, auto_int, auto_uint8, auto_uint16,
is_hexstr, JsonEncoder
+from pySim.utils import bertlv_parse_one
+
from pySim.construct import filter_dict, parse_construct, build_construct
from pySim.jsonpath import js_path_modify
from pySim.commands import SimCardCommands
@@ -774,6 +776,25 @@
raise NotImplementedError(
"%s encoder not yet implemented. Patches welcome." % self)
+ @staticmethod
+ def export(as_json: bool, lchan):
+ """
+ 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.
+ """
+
+ if lchan.selected_file_structure() != 'transparent':
+ raise ValueError("selected file has structure type '%s',
expecting a file with structure 'transparent'" %
+ lchan.selected_file_structure())
+ export_str = ""
+ if as_json:
+ result = lchan.read_binary_dec()
+ export_str += ("update_binary_decoded '%s'\n" %
json.dumps(result[0], cls=JsonEncoder))
+ else:
+ result = lchan.read_binary()
+ export_str += ("update_binary %s\n" % str(result[0]))
+ return export_str.strip()
+
class LinFixedEF(CardEF):
"""Linear Fixed EF (Entry File) in the smart card filesystem.
@@ -1044,6 +1065,54 @@
raise NotImplementedError(
"%s encoder not yet implemented. Patches welcome." % self)
+ @staticmethod
+ def export(as_json: bool, lchan):
+ """
+ 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.
+ """
+
+ # A CyclicEF is a subclass of LinFixedEF.
+ if lchan.selected_file_structure() != 'linear_fixed' and
lchan.selected_file_structure() != 'cyclic':
+ raise ValueError("selected file has structure type '%s',
expecting a file with structure 'linear_fixed' or 'cyclic'" %
+ lchan.selected_file_structure())
+
+ export_str = ""
+
+ # Use number of records specified in select response
+ num_of_rec = lchan.selected_file_num_of_rec()
+ if num_of_rec:
+ for r in range(1, num_of_rec + 1):
+ if as_json:
+ result = lchan.read_record_dec(r)
+ export_str += ("update_record_decoded %d '%s'\n" %
(r, json.dumps(result[0], cls=JsonEncoder)))
+ else:
+ result = lchan.read_record(r)
+ export_str += ("update_record %d %s\n" % (r,
str(result[0])))
+
+ # In case the select response does not return the number of records, read until
we hit the first record that
+ # cannot be read.
+ else:
+ r = 1
+ while True:
+ try:
+ if as_json:
+ result = lchan.read_record_dec(r)
+ export_str += ("update_record_decoded %d
'%s'\n" % (r, json.dumps(result[0], cls=JsonEncoder)))
+ else:
+ result = lchan.read_record(r)
+ export_str += ("update_record %d %s\n" % (r,
str(result[0])))
+ except SwMatchError as e:
+ # We are past the last valid record - stop
+ if e.sw_actual == "9402":
+ break
+ # Some other problem occurred
+ else:
+ raise e
+ r = r + 1
+
+ return export_str.strip()
+
class CyclicEF(LinFixedEF):
"""Cyclic EF (Entry File) in the smart card
filesystem"""
@@ -1264,6 +1333,33 @@
self.size = size
self.shell_commands = [self.ShellCommands()]
+ @staticmethod
+ def export(as_json: bool, lchan):
+ """
+ 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.
+ """
+
+ if lchan.selected_file_structure() != 'ber_tlv':
+ raise ValueError("selected file has structure type '%s',
expecting a file with structure 'ber_tlv'" %
+ lchan.selected_file_structure())
+
+ # TODO: Add JSON output as soon as we have a set_data_decoded command and a
retrieve_data_dec method.
+ if as_json:
+ raise NotImplementedError("BerTlvEF encoder not yet implemented. Patches
welcome.")
+
+ export_str = ""
+ tags = lchan.retrieve_tags()
+ if tags == []:
+ export_str += "# empty file, no tags"
+ else:
+ for t in tags:
+ result = lchan.retrieve_data(t)
+ (tag, l, val, remainer) = bertlv_parse_one(h2b(result[0]))
+ export_str += ("set_data 0x%02x %s\n" % (t, b2h(val)))
+ return export_str.strip()
+
+
def interpret_sw(sw_data: dict, sw: str):
"""Interpret a given status word.
--
To view, visit
https://gerrit.osmocom.org/c/pysim/+/37612?usp=email
To unsubscribe, or for help writing mail filters, visit
https://gerrit.osmocom.org/settings
Gerrit-Project: pysim
Gerrit-Branch: master
Gerrit-Change-Id: Icc2ee60cfc4379411744ca1033d79a1ee9cff5a6
Gerrit-Change-Number: 37612
Gerrit-PatchSet: 1
Gerrit-Owner: dexter <pmaier(a)sysmocom.de>
Gerrit-MessageType: newchange