def _make_wrapped_field(self, name, field, is_fake=False, full_name=None): """Creates the field lazily. If it's a simple field, wraps it in a container that adds extra features. If it's a nested layer, creates a layer for it. If it's an intermediate layer, copies over the relevant fields and creates a new layer for it. """ if not full_name: full_name = '%s.%s' % (self._full_name, name) if is_fake: # Populate with all fields that are supposed to be inside of it field = { key: value for key, value in self._all_fields.items() if key.startswith(full_name) } if isinstance(field, dict): if name.endswith('_tree'): name = name.replace('_tree', '') full_name = '%s.%s' % (self._full_name, name) return JsonLayer(name, field, full_name=full_name, is_intermediate=is_fake) elif isinstance(field, list): # For whatever reason in list-type object it goes back to using the original parent name return [ self._make_wrapped_field( name, field_part, full_name=self._full_name.split('.')[0]) for field_part in field ] return LayerFieldsContainer(LayerField(name=name, value=field))
def get_layer_field(packet: RawPacket, field_uri: str) -> Any: """ Get a given layer field from the packet. :param packet: The packet. :param field_uri: The layer field URI. :return: The specified layer field. """ assert isinstance(packet, RawPacket) secs = field_uri.split('.') layer_name = secs[0] if is_layer_field(field_uri): candidate_layers = _get_candidate_layers(packet, layer_name) for layer in candidate_layers: v = layer.get_field(field_uri) if v is not None: try: v = _LAYER_FIELDS[field_uri](v) print("[%s = %r] " % (field_uri, v), file=sys.stderr) return v except Exception as ex: raise ValueError('can not parse field %s = %r' % (field_uri, (v.get_default_value(), v.raw_value))) from ex print("[%s = %s] " % (field_uri, "null"), file=sys.stderr) return nullField elif is_layer_field_container(field_uri): from pktverify.layer_fields_container import LayerFieldsContainer return LayerFieldsContainer(packet, field_uri) else: raise NotImplementedError('Field %s is not valid, please add it to `_LAYER_FIELDS`' % field_uri)
def _add_field(self, key: str, val: str): logging.debug("layer %s add field: %s = %s", self.layer_name, key, val) field = LayerField(name=key, value=val) all_fields = self._layer._all_fields if key not in all_fields: all_fields[key] = LayerFieldsContainer(main_field=field) else: all_fields[key].fields.append(field)
def __init__(self, xml_obj=None, raw_mode=False): self.raw_mode = raw_mode self._layer_name = xml_obj.attrib['name'] self._all_fields = {} # We copy over all the fields from the XML object # Note: we don't read lazily from the XML because the lxml objects are very memory-inefficient # so we'd rather not save them. for field in xml_obj.findall('.//field'): attributes = dict(field.attrib) field_obj = LayerField(**attributes) if attributes['name'] in self._all_fields: # Field name already exists, add this field to the container. self._all_fields[attributes['name']].add_field(field_obj) else: self._all_fields[attributes['name']] = LayerFieldsContainer(field_obj)