mirror of
https://gitea.osmocom.org/sim-card/pysim.git
synced 2026-03-18 19:38:34 +03:00
Compare commits
3 Commits
pmaier/fix
...
master
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
0634f77308 | ||
|
|
a5a5865c7c | ||
|
|
3752aeb94e |
@@ -128,7 +128,7 @@ class EF_AD(TransparentEF):
|
|||||||
cell_test = 0x04
|
cell_test = 0x04
|
||||||
|
|
||||||
def __init__(self, fid='6f43', sfid=None, name='EF.AD',
|
def __init__(self, fid='6f43', sfid=None, name='EF.AD',
|
||||||
desc='Service Provider Name', size=(3, None), **kwargs):
|
desc='Administrative Data', size=(3, None), **kwargs):
|
||||||
super().__init__(fid, sfid=sfid, name=name, desc=desc, size=size, **kwargs)
|
super().__init__(fid, sfid=sfid, name=name, desc=desc, size=size, **kwargs)
|
||||||
self._construct = Struct(
|
self._construct = Struct(
|
||||||
# Byte 1: Display Condition
|
# Byte 1: Display Condition
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ import abc
|
|||||||
import requests
|
import requests
|
||||||
import logging
|
import logging
|
||||||
import json
|
import json
|
||||||
from typing import Optional
|
from typing import Optional, Tuple
|
||||||
import base64
|
import base64
|
||||||
from twisted.web.server import Request
|
from twisted.web.server import Request
|
||||||
|
|
||||||
@@ -180,7 +180,7 @@ class JsonHttpApiFunction(abc.ABC):
|
|||||||
# receives from the a requesting client. The same applies vice versa to class variables that have an "output_"
|
# receives from the a requesting client. The same applies vice versa to class variables that have an "output_"
|
||||||
# prefix.
|
# prefix.
|
||||||
|
|
||||||
# path of the API function (e.g. '/gsma/rsp2/es2plus/confirmOrder')
|
# path of the API function (e.g. '/gsma/rsp2/es2plus/confirmOrder', see also method rewrite_url).
|
||||||
path = None
|
path = None
|
||||||
|
|
||||||
# dictionary of input parameters. key is parameter name, value is ApiParam class
|
# dictionary of input parameters. key is parameter name, value is ApiParam class
|
||||||
@@ -336,6 +336,22 @@ class JsonHttpApiFunction(abc.ABC):
|
|||||||
output[p] = p_class.decode(v)
|
output[p] = p_class.decode(v)
|
||||||
return output
|
return output
|
||||||
|
|
||||||
|
def rewrite_url(self, data: dict, url: str) -> Tuple[dict, str]:
|
||||||
|
"""
|
||||||
|
Rewrite a static URL using information passed in the data dict. This method may be overloaded by a derived
|
||||||
|
class to allow fully dynamic URLs. The input parameters required for the URL rewriting may be passed using
|
||||||
|
data parameter. In case those parameters are additional parameters that are not intended to be passed to
|
||||||
|
the encode_client method later, they must be removed explcitly.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
data: (see JsonHttpApiClient and JsonHttpApiServer)
|
||||||
|
url: statically generated URL string (see comment in JsonHttpApiClient)
|
||||||
|
"""
|
||||||
|
|
||||||
|
# This implementation is a placeholder in which we do not perform any URL rewriting. We just pass through data
|
||||||
|
# and url unmodified.
|
||||||
|
return data, url
|
||||||
|
|
||||||
class JsonHttpApiClient():
|
class JsonHttpApiClient():
|
||||||
def __init__(self, api_func: JsonHttpApiFunction, url_prefix: str, func_req_id: Optional[str],
|
def __init__(self, api_func: JsonHttpApiFunction, url_prefix: str, func_req_id: Optional[str],
|
||||||
session: requests.Session):
|
session: requests.Session):
|
||||||
@@ -352,8 +368,16 @@ class JsonHttpApiClient():
|
|||||||
self.session = session
|
self.session = session
|
||||||
|
|
||||||
def call(self, data: dict, func_call_id: Optional[str] = None, timeout=10) -> Optional[dict]:
|
def call(self, data: dict, func_call_id: Optional[str] = None, timeout=10) -> Optional[dict]:
|
||||||
"""Make an API call to the HTTP API endpoint represented by this object. Input data is passed in `data` as
|
"""
|
||||||
json-serializable dict. Output data is returned as json-deserialized dict."""
|
Make an API call to the HTTP API endpoint represented by this object. Input data is passed in `data` as
|
||||||
|
json-serializable fields. `data` may also contain additional parameters required for URL rewriting (see
|
||||||
|
rewrite_url in class JsonHttpApiFunction). Output data is returned as json-deserialized dict.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
data: Input data required to perform the request.
|
||||||
|
func_call_id: Function Call Identifier, if present a header field is generated automatically.
|
||||||
|
timeout: Maximum amount of time to wait for the request to complete.
|
||||||
|
"""
|
||||||
|
|
||||||
# In case a function caller ID is supplied, use it together with the stored function requestor ID to generate
|
# In case a function caller ID is supplied, use it together with the stored function requestor ID to generate
|
||||||
# and prepend the header field according to SGP.22, section 6.5.1.1 and 6.5.1.3. (the presence of the header
|
# and prepend the header field according to SGP.22, section 6.5.1.1 and 6.5.1.3. (the presence of the header
|
||||||
@@ -362,6 +386,11 @@ class JsonHttpApiClient():
|
|||||||
data = {'header' : {'functionRequesterIdentifier': self.func_req_id,
|
data = {'header' : {'functionRequesterIdentifier': self.func_req_id,
|
||||||
'functionCallIdentifier': func_call_id}} | data
|
'functionCallIdentifier': func_call_id}} | data
|
||||||
|
|
||||||
|
# The URL used for the HTTP request (see below) normally consists of the initially given url_prefix
|
||||||
|
# concatenated with the path defined by the JsonHttpApiFunction definition. This static URL path may be
|
||||||
|
# rewritten by rewrite_url method defined in the JsonHttpApiFunction.
|
||||||
|
data, url = self.api_func.rewrite_url(data, self.url_prefix + self.api_func.path)
|
||||||
|
|
||||||
# Encode the message (the presence of mandatory fields is checked during encoding)
|
# Encode the message (the presence of mandatory fields is checked during encoding)
|
||||||
encoded = json.dumps(self.api_func.encode_client(data))
|
encoded = json.dumps(self.api_func.encode_client(data))
|
||||||
|
|
||||||
@@ -373,7 +402,6 @@ class JsonHttpApiClient():
|
|||||||
req_headers.update(self.api_func.extra_http_req_headers)
|
req_headers.update(self.api_func.extra_http_req_headers)
|
||||||
|
|
||||||
# Perform HTTP request
|
# Perform HTTP request
|
||||||
url = self.url_prefix + self.api_func.path
|
|
||||||
logger.debug("HTTP REQ %s - hdr: %s '%s'" % (url, req_headers, encoded))
|
logger.debug("HTTP REQ %s - hdr: %s '%s'" % (url, req_headers, encoded))
|
||||||
response = self.session.request(self.api_func.http_method, url, data=encoded, headers=req_headers, timeout=timeout)
|
response = self.session.request(self.api_func.http_method, url, data=encoded, headers=req_headers, timeout=timeout)
|
||||||
logger.debug("HTTP RSP-STS: [%u] hdr: %s" % (response.status_code, response.headers))
|
logger.debug("HTTP RSP-STS: [%u] hdr: %s" % (response.status_code, response.headers))
|
||||||
|
|||||||
@@ -151,6 +151,8 @@ class File:
|
|||||||
self.df_name = None
|
self.df_name = None
|
||||||
self.fill_pattern = None
|
self.fill_pattern = None
|
||||||
self.fill_pattern_repeat = False
|
self.fill_pattern_repeat = False
|
||||||
|
self.pstdo = None # pinStatusTemplateDO, mandatory for DF/ADF
|
||||||
|
self.lcsi = None # optional life cycle status indicator
|
||||||
# apply some defaults from profile
|
# apply some defaults from profile
|
||||||
if self.template:
|
if self.template:
|
||||||
self.from_template(self.template)
|
self.from_template(self.template)
|
||||||
@@ -278,6 +280,8 @@ class File:
|
|||||||
elif self.file_type in ['MF', 'DF', 'ADF']:
|
elif self.file_type in ['MF', 'DF', 'ADF']:
|
||||||
fdb_dec['file_type'] = 'df'
|
fdb_dec['file_type'] = 'df'
|
||||||
fdb_dec['structure'] = 'no_info_given'
|
fdb_dec['structure'] = 'no_info_given'
|
||||||
|
# pinStatusTemplateDO is mandatory for DF/ADF
|
||||||
|
fileDescriptor['pinStatusTemplateDO'] = self.pstdo
|
||||||
# build file descriptor based on above input data
|
# build file descriptor based on above input data
|
||||||
fd_dict = {}
|
fd_dict = {}
|
||||||
if len(fdb_dec):
|
if len(fdb_dec):
|
||||||
@@ -304,6 +308,8 @@ class File:
|
|||||||
# desired fill or repeat pattern in the "proprietaryEFInfo" element for the EF in Profiles
|
# desired fill or repeat pattern in the "proprietaryEFInfo" element for the EF in Profiles
|
||||||
# downloaded to a V2.2 or earlier eUICC.
|
# downloaded to a V2.2 or earlier eUICC.
|
||||||
fileDescriptor['proprietaryEFInfo'] = pefi
|
fileDescriptor['proprietaryEFInfo'] = pefi
|
||||||
|
if self.lcsi:
|
||||||
|
fileDescriptor['lcsi'] = self.lcsi
|
||||||
logger.debug("%s: to_fileDescriptor(%s)" % (self, fileDescriptor))
|
logger.debug("%s: to_fileDescriptor(%s)" % (self, fileDescriptor))
|
||||||
return fileDescriptor
|
return fileDescriptor
|
||||||
|
|
||||||
@@ -323,6 +329,8 @@ class File:
|
|||||||
if efFileSize:
|
if efFileSize:
|
||||||
self._file_size = self._decode_file_size(efFileSize)
|
self._file_size = self._decode_file_size(efFileSize)
|
||||||
|
|
||||||
|
self.pstdo = fileDescriptor.get('pinStatusTemplateDO', None)
|
||||||
|
self.lcsi = fileDescriptor.get('lcsi', None)
|
||||||
pefi = fileDescriptor.get('proprietaryEFInfo', {})
|
pefi = fileDescriptor.get('proprietaryEFInfo', {})
|
||||||
securityAttributesReferenced = fileDescriptor.get('securityAttributesReferenced', None)
|
securityAttributesReferenced = fileDescriptor.get('securityAttributesReferenced', None)
|
||||||
if securityAttributesReferenced:
|
if securityAttributesReferenced:
|
||||||
|
|||||||
Reference in New Issue
Block a user