This is merely a historical archive of years 2008-2021, before the migration to mailman3.
A maintained and still updated list archive can be found at https://lists.osmocom.org/hyperkitty/list/gerrit-log@lists.osmocom.org/.
laforge gerrit-no-reply at lists.osmocom.orglaforge has submitted this change. ( https://gerrit.osmocom.org/c/pysim/+/23661 ) Change subject: pySim-shell: JSONpath support for updating files/records ...................................................................... pySim-shell: JSONpath support for updating files/records Change-Id: Iad09b3d878b8b58ad34cb549c80f8a6eb3149faa --- M contrib/jenkins.sh M docs/shell.rst M pySim/filesystem.py A pySim/jsonpath.py M requirements.txt M setup.py 6 files changed, 94 insertions(+), 2 deletions(-) Approvals: laforge: Looks good to me, approved Jenkins Builder: Verified diff --git a/contrib/jenkins.sh b/contrib/jenkins.sh index 60061e3..f83e6a5 100755 --- a/contrib/jenkins.sh +++ b/contrib/jenkins.sh @@ -14,6 +14,7 @@ pip install pytlv pip install pyyaml pip install cmd2 +pip install jsonpath-ng # Execute automatically discovered unit tests first python -m unittest discover -v -s tests/ diff --git a/docs/shell.rst b/docs/shell.rst index 2edebbf..3cfc849 100644 --- a/docs/shell.rst +++ b/docs/shell.rst @@ -226,6 +226,33 @@ :module: pySim.filesystem :func: TransparentEF.ShellCommands.upd_bin_dec_parser +In normal operation, update_binary_decoded needs a JSON document representing the entire file contents as +input. This can be inconvenient if you want to keep 99% of the content but just toggle one specific +parameter. That's where the JSONpath support comes in handy: You can specify a JSONpath to an element +inside the document as well as a new value for tat field: + +Th below example demonstrates this by modifying the ofm field within EF.AD: + +:: + + pySIM-shell (MF/ADF.USIM/EF.AD)> read_binary_decoded + { + "ms_operation_mode": "normal", + "specific_facilities": { + "ofm": true + }, + "len_of_mnc_in_imsi": 2 + } + pySIM-shell (MF/ADF.USIM/EF.AD)> update_binary_decoded --json-path specific_facilities.ofm false + pySIM-shell (MF/ADF.USIM/EF.AD)> read_binary_decoded + { + "ms_operation_mode": "normal", + "specific_facilities": { + "ofm": false + }, + "len_of_mnc_in_imsi": 2 + } + cmd2 settable parameters diff --git a/pySim/filesystem.py b/pySim/filesystem.py index a65a764..f8443f3 100644 --- a/pySim/filesystem.py +++ b/pySim/filesystem.py @@ -35,6 +35,7 @@ from pySim.utils import sw_match, h2b, b2h, is_hex from pySim.exceptions import * +from pySim.jsonpath import js_path_find, js_path_modify class CardFile(object): """Base class for all objects in the smart card filesystem. @@ -418,10 +419,16 @@ upd_bin_dec_parser = argparse.ArgumentParser() upd_bin_dec_parser.add_argument('data', help='Abstract data (JSON format) to write') + upd_bin_dec_parser.add_argument('--json-path', type=str, + help='JSON path to modify specific element of file only') @cmd2.with_argparser(upd_bin_dec_parser) def do_update_binary_decoded(self, opts): """Encode + Update (Write) data of a transparent EF""" - data_json = json.loads(opts.data) + if opts.json_path: + (data_json, sw) = self._cmd.rs.read_binary_dec() + js_path_modify(data_json, opts.json_path, json.loads(opts.data)) + else: + data_json = json.loads(opts.data) (data, sw) = self._cmd.rs.update_binary_dec(data_json) if data: self._cmd.poutput_json(data) @@ -574,10 +581,17 @@ upd_rec_dec_parser = argparse.ArgumentParser() upd_rec_dec_parser.add_argument('record_nr', type=int, help='Number of record to be read') upd_rec_dec_parser.add_argument('data', help='Data bytes (hex format) to write') + upd_rec_dec_parser.add_argument('--json-path', type=str, + help='JSON path to modify specific element of record only') @cmd2.with_argparser(upd_rec_dec_parser) def do_update_record_decoded(self, opts): """Encode + Update (write) data to a record-oriented EF""" - (data, sw) = self._cmd.rs.update_record_dec(opts.record_nr, opts.data) + if opts.json_path: + (data_json, sw) = self._cmd.rs.read_record_dec(opts.record_nr) + js_path_modify(data_json, opts.json_path, json.loads(opts.data)) + else: + data_json = json.loads(opts.data) + (data, sw) = self._cmd.rs.update_record_dec(opts.record_nr, data_json) if data: self._cmd.poutput(data) diff --git a/pySim/jsonpath.py b/pySim/jsonpath.py new file mode 100644 index 0000000..98dbd75 --- /dev/null +++ b/pySim/jsonpath.py @@ -0,0 +1,48 @@ +# coding=utf-8 +import json +import pprint +import jsonpath_ng + +"""JSONpath utility functions as needed within pysim. + +As pySim-sell has the ability to represent SIM files as JSON strings, +adding JSONpath allows us to conveniently modify individual sub-fields +of a file or record in its JSON representation. +""" + +# (C) 2021 by Harald Welte <laforge at osmocom.org> +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. + +def js_path_find(js_dict, js_path): + """Find/Match a JSON path within a given JSON-serializable dict. + Args: + js_dict : JSON-serializable dict to operate on + js_path : JSONpath string + Returns: Result of the JSONpath expression + """ + jsonpath_expr = jsonpath_ng.parse(js_path) + return jsonpath_expr.find(js_dict) + +def js_path_modify(js_dict, js_path, new_val): + """Find/Match a JSON path within a given JSON-serializable dict. + Args: + js_dict : JSON-serializable dict to operate on + js_path : JSONpath string + new_val : New value for field in js_dict at js_path + """ + jsonpath_expr = jsonpath_ng.parse(js_path) + jsonpath_expr.find(js_dict) + jsonpath_expr.update(js_dict, new_val) + diff --git a/requirements.txt b/requirements.txt index 978a3db..f203ed1 100644 --- a/requirements.txt +++ b/requirements.txt @@ -2,3 +2,4 @@ serial pytlv cmd2 +jsonpath-ng diff --git a/setup.py b/setup.py index d9f742c..a02e327 100644 --- a/setup.py +++ b/setup.py @@ -13,6 +13,7 @@ "serial", "pytlv", "cmd2" + "jsonpath-ng" ], scripts=[ 'pySim-prog.py', -- To view, visit https://gerrit.osmocom.org/c/pysim/+/23661 To unsubscribe, or for help writing mail filters, visit https://gerrit.osmocom.org/settings Gerrit-Project: pysim Gerrit-Branch: master Gerrit-Change-Id: Iad09b3d878b8b58ad34cb549c80f8a6eb3149faa Gerrit-Change-Number: 23661 Gerrit-PatchSet: 6 Gerrit-Owner: laforge <laforge at osmocom.org> Gerrit-Reviewer: Falkenber9 <robert.falkenberg at tu-dortmund.de> Gerrit-Reviewer: Jenkins Builder Gerrit-Reviewer: dexter <pmaier at sysmocom.de> Gerrit-Reviewer: fixeria <vyanitskiy at sysmocom.de> Gerrit-Reviewer: herlesupreeth <herlesupreeth at gmail.com> Gerrit-Reviewer: laforge <laforge at osmocom.org> Gerrit-MessageType: merged -------------- next part -------------- An HTML attachment was scrubbed... URL: <http://lists.osmocom.org/pipermail/gerrit-log/attachments/20210407/ff351455/attachment.htm>