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
This commit is contained in:
@@ -599,66 +599,14 @@ class PySimCommands(CommandSet):
|
|||||||
self._cmd.poutput("# directory: %s (%s)" % (df_path, df_path_fid))
|
self._cmd.poutput("# directory: %s (%s)" % (df_path, df_path_fid))
|
||||||
try:
|
try:
|
||||||
fcp_dec = self._cmd.lchan.select(filename, self._cmd)
|
fcp_dec = self._cmd.lchan.select(filename, self._cmd)
|
||||||
self._cmd.poutput("# file: %s (%s)" % (
|
self._cmd.poutput("# file: %s (%s)" %
|
||||||
self._cmd.lchan.selected_file.name, self._cmd.lchan.selected_file.fid))
|
(self._cmd.lchan.selected_file.name, self._cmd.lchan.selected_file.fid))
|
||||||
|
self._cmd.poutput("# structure: %s" % self._cmd.lchan.selected_file_structure())
|
||||||
structure = self._cmd.lchan.selected_file_structure()
|
|
||||||
self._cmd.poutput("# structure: %s" % str(structure))
|
|
||||||
self._cmd.poutput("# RAW FCP Template: %s" % str(self._cmd.lchan.selected_file_fcp_hex))
|
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("# 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:
|
except Exception as e:
|
||||||
bad_file_str = df_path + "/" + str(filename) + ", " + str(e)
|
bad_file_str = df_path + "/" + str(filename) + ", " + str(e)
|
||||||
self._cmd.poutput("# bad file: %s" % bad_file_str)
|
self._cmd.poutput("# bad file: %s" % bad_file_str)
|
||||||
|
|||||||
@@ -35,10 +35,13 @@ import cmd2
|
|||||||
from cmd2 import CommandSet, with_default_category
|
from cmd2 import CommandSet, with_default_category
|
||||||
from smartcard.util import toBytes
|
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.construct import filter_dict, parse_construct, build_construct
|
||||||
from pySim.jsonpath import js_path_modify
|
from pySim.jsonpath import js_path_modify
|
||||||
from pySim.commands import SimCardCommands
|
from pySim.commands import SimCardCommands
|
||||||
|
from pySim.exceptions import SwMatchError
|
||||||
|
|
||||||
# int: a single service is associated with this file
|
# int: a single service is associated with this file
|
||||||
# list: any of the listed services requires this file
|
# list: any of the listed services requires this file
|
||||||
@@ -774,6 +777,25 @@ class TransparentEF(CardEF):
|
|||||||
raise NotImplementedError(
|
raise NotImplementedError(
|
||||||
"%s encoder not yet implemented. Patches welcome." % self)
|
"%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):
|
class LinFixedEF(CardEF):
|
||||||
"""Linear Fixed EF (Entry File) in the smart card filesystem.
|
"""Linear Fixed EF (Entry File) in the smart card filesystem.
|
||||||
@@ -1044,6 +1066,54 @@ class LinFixedEF(CardEF):
|
|||||||
raise NotImplementedError(
|
raise NotImplementedError(
|
||||||
"%s encoder not yet implemented. Patches welcome." % self)
|
"%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):
|
class CyclicEF(LinFixedEF):
|
||||||
"""Cyclic EF (Entry File) in the smart card filesystem"""
|
"""Cyclic EF (Entry File) in the smart card filesystem"""
|
||||||
@@ -1264,6 +1334,33 @@ class BerTlvEF(CardEF):
|
|||||||
self.size = size
|
self.size = size
|
||||||
self.shell_commands = [self.ShellCommands()]
|
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):
|
def interpret_sw(sw_data: dict, sw: str):
|
||||||
"""Interpret a given status word.
|
"""Interpret a given status word.
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user