/* * Decode the chunk of XML text encoding INTEGER. */ static enum xer_pbd_rval BOOLEAN__xer_body_decode(asn_TYPE_descriptor_t *td, void *sptr, const void *chunk_buf, size_t chunk_size) { BOOLEAN_t *st = (BOOLEAN_t *)sptr; const char *p = (const char *)chunk_buf; (void)td; if(chunk_size && p[0] == 0x3c /* '<' */) { switch(xer_check_tag(chunk_buf, chunk_size, "false")) { case XCT_BOTH: /* "<false/>" */ *st = 0; break; case XCT_UNKNOWN_BO: if(xer_check_tag(chunk_buf, chunk_size, "true") != XCT_BOTH) return XPBD_BROKEN_ENCODING; /* "<true/>" */ *st = 1; /* Or 0xff as in DER?.. */ break; default: return XPBD_BROKEN_ENCODING; } return XPBD_BODY_CONSUMED; } else { return XPBD_BROKEN_ENCODING; } }
/* * Decode the XER (XML) data. */ asn_dec_rval_t SET_OF_decode_xer(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td, void **struct_ptr, const char *opt_mname, const void *buf_ptr, size_t size) { /* * Bring closer parts of structure description. */ asn_SET_OF_specifics_t *specs = (asn_SET_OF_specifics_t *)td->specifics; asn_TYPE_member_t *element = td->elements; const char *elm_tag; const char *xml_tag = opt_mname ? opt_mname : td->xml_tag; /* * ... and parts of the structure being constructed. */ void *st = *struct_ptr; /* Target structure. */ asn_struct_ctx_t *ctx; /* Decoder context */ asn_dec_rval_t rval; /* Return value from a decoder */ ssize_t consumed_myself = 0; /* Consumed bytes from ptr */ /* * Create the target structure if it is not present already. */ if(st == 0) { st = *struct_ptr = CALLOC(1, specs->struct_size); if(st == 0) RETURN(RC_FAIL); } /* Which tag is expected for the downstream */ if(specs->as_XMLValueList) { elm_tag = (specs->as_XMLValueList == 1) ? 0 : ""; } else { elm_tag = (*element->name) ? element->name : element->type->xml_tag; } /* * Restore parsing context. */ ctx = (asn_struct_ctx_t *)((char *)st + specs->ctx_offset); /* * Phases of XER/XML processing: * Phase 0: Check that the opening tag matches our expectations. * Phase 1: Processing body and reacting on closing tag. * Phase 2: Processing inner type. */ for(; ctx->phase <= 2;) { pxer_chunk_type_e ch_type; /* XER chunk type */ ssize_t ch_size; /* Chunk size */ xer_check_tag_e tcv; /* Tag check value */ /* * Go inside the inner member of a set. */ if(ctx->phase == 2) { asn_dec_rval_t tmprval; /* Invoke the inner type decoder, m.b. multiple times */ ASN_DEBUG("XER/SET OF element [%s]", elm_tag); tmprval = element->type->xer_decoder(opt_codec_ctx, element->type, &ctx->ptr, elm_tag, buf_ptr, size); if(tmprval.code == RC_OK) { asn_anonymous_set_ *list = _A_SET_FROM_VOID(st); if(ASN_SET_ADD(list, ctx->ptr) != 0) RETURN(RC_FAIL); ctx->ptr = 0; XER_ADVANCE(tmprval.consumed); } else { XER_ADVANCE(tmprval.consumed); RETURN(tmprval.code); } ctx->phase = 1; /* Back to body processing */ ASN_DEBUG("XER/SET OF phase => %d", ctx->phase); /* Fall through */ } /* * Get the next part of the XML stream. */ ch_size = xer_next_token(&ctx->context, buf_ptr, size, &ch_type); switch(ch_size) { case -1: RETURN(RC_FAIL); case 0: RETURN(RC_WMORE); default: switch(ch_type) { case PXER_COMMENT: /* Got XML comment */ case PXER_TEXT: /* Ignore free-standing text */ XER_ADVANCE(ch_size); /* Skip silently */ continue; case PXER_TAG: break; /* Check the rest down there */ } } tcv = xer_check_tag(buf_ptr, ch_size, xml_tag); ASN_DEBUG("XER/SET OF: tcv = %d, ph=%d t=%s", tcv, ctx->phase, xml_tag); switch(tcv) { case XCT_CLOSING: if(ctx->phase == 0) break; ctx->phase = 0; /* Fall through */ case XCT_BOTH: if(ctx->phase == 0) { /* No more things to decode */ XER_ADVANCE(ch_size); ctx->phase = 3; /* Phase out */ RETURN(RC_OK); } /* Fall through */ case XCT_OPENING: if(ctx->phase == 0) { XER_ADVANCE(ch_size); ctx->phase = 1; /* Processing body phase */ continue; } /* Fall through */ case XCT_UNKNOWN_OP: case XCT_UNKNOWN_BO: ASN_DEBUG("XER/SET OF: tcv=%d, ph=%d", tcv, ctx->phase); if(ctx->phase == 1) { /* * Process a single possible member. */ ctx->phase = 2; continue; } /* Fall through */ default: break; } ASN_DEBUG("Unexpected XML tag in SET OF"); break; } ctx->phase = 3; /* "Phase out" on hard failure */ RETURN(RC_FAIL); }
/* * Decode the XER (XML) data. */ asn_dec_rval_t SEQUENCE_decode_xer(Allocator * allocator, asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td, void **struct_ptr, const char *opt_mname, const void *buf_ptr, size_t size) { /* * Bring closer parts of structure description. */ asn_SEQUENCE_specifics_t *specs = (asn_SEQUENCE_specifics_t *)td->specifics; asn_TYPE_member_t *elements = td->elements; const char *xml_tag = opt_mname ? opt_mname : td->xml_tag; /* * ... and parts of the structure being constructed. */ void *st = *struct_ptr; /* Target structure. */ asn_struct_ctx_t *ctx; /* Decoder context */ asn_dec_rval_t rval; /* Return value from a decoder */ ssize_t consumed_myself = 0; /* Consumed bytes from ptr */ int edx; /* Element index */ int edx_end; /* * Create the target structure if it is not present already. */ if(st == 0) { st = *struct_ptr = CXX_ALLOC_WRAP CALLOC(1, specs->struct_size); if(st == 0) RETURN(RC_FAIL); } /* * Restore parsing context. */ ctx = (asn_struct_ctx_t *)((char *)st + specs->ctx_offset); /* * Phases of XER/XML processing: * Phase 0: Check that the opening tag matches our expectations. * Phase 1: Processing body and reacting on closing tag. * Phase 2: Processing inner type. * Phase 3: Skipping unknown extensions. * Phase 4: PHASED OUT */ for(edx = ctx->step; ctx->phase <= 3;) { pxer_chunk_type_e ch_type; /* XER chunk type */ ssize_t ch_size; /* Chunk size */ xer_check_tag_e tcv; /* Tag check value */ asn_TYPE_member_t *elm; int n; /* * Go inside the inner member of a sequence. */ if(ctx->phase == 2) { asn_dec_rval_t tmprval; void *memb_ptr; /* Pointer to the member */ void **memb_ptr2; /* Pointer to that pointer */ elm = &td->elements[edx]; if(elm->flags & ATF_POINTER) { /* Member is a pointer to another structure */ memb_ptr2 = (void **)((char *)st + elm->memb_offset); } else { memb_ptr = (char *)st + elm->memb_offset; memb_ptr2 = &memb_ptr; } /* Invoke the inner type decoder, m.b. multiple times */ tmprval = elm->type->xer_decoder(allocator, opt_codec_ctx, elm->type, memb_ptr2, elm->name, buf_ptr, size); XER_ADVANCE(tmprval.consumed); if(tmprval.code != RC_OK) RETURN(tmprval.code); ctx->phase = 1; /* Back to body processing */ ctx->step = ++edx; ASN_DEBUG("XER/SEQUENCE phase => %d, step => %d", ctx->phase, ctx->step); /* Fall through */ } /* * Get the next part of the XML stream. */ ch_size = xer_next_token(&ctx->context, buf_ptr, size, &ch_type); switch(ch_size) { case -1: RETURN(RC_FAIL); case 0: RETURN(RC_WMORE); default: switch(ch_type) { case PXER_COMMENT: /* Got XML comment */ case PXER_TEXT: /* Ignore free-standing text */ XER_ADVANCE(ch_size); /* Skip silently */ continue; case PXER_TAG: break; /* Check the rest down there */ } } tcv = xer_check_tag(buf_ptr, ch_size, xml_tag); ASN_DEBUG("XER/SEQUENCE: tcv = %d, ph=%d [%s]", tcv, ctx->phase, xml_tag); /* Skip the extensions section */ if(ctx->phase == 3) { switch(xer_skip_unknown(tcv, &ctx->left)) { case -1: ctx->phase = 4; RETURN(RC_FAIL); case 0: XER_ADVANCE(ch_size); continue; case 1: XER_ADVANCE(ch_size); ctx->phase = 1; continue; case 2: ctx->phase = 1; break; } } switch(tcv) { case XCT_CLOSING: if(ctx->phase == 0) break; ctx->phase = 0; /* Fall through */ case XCT_BOTH: if(ctx->phase == 0) { if(edx >= td->elements_count || /* Explicit OPTIONAL specs reaches the end */ (edx + elements[edx].optional == td->elements_count) || /* All extensions are optional */ (IN_EXTENSION_GROUP(specs, edx) && specs->ext_before > td->elements_count) ) { XER_ADVANCE(ch_size); ctx->phase = 4; /* Phase out */ RETURN(RC_OK); } else { ASN_DEBUG("Premature end of XER SEQUENCE"); RETURN(RC_FAIL); } } /* Fall through */ case XCT_OPENING: if(ctx->phase == 0) { XER_ADVANCE(ch_size); ctx->phase = 1; /* Processing body phase */ continue; } /* Fall through */ case XCT_UNKNOWN_OP: case XCT_UNKNOWN_BO: ASN_DEBUG("XER/SEQUENCE: tcv=%d, ph=%d, edx=%d", tcv, ctx->phase, edx); if(ctx->phase != 1) { break; /* Really unexpected */ } if(edx < td->elements_count) { /* * Search which member corresponds to this tag. */ edx_end = edx + elements[edx].optional + 1; if(edx_end > td->elements_count) edx_end = td->elements_count; for(n = edx; n < edx_end; n++) { elm = &td->elements[n]; tcv = xer_check_tag(buf_ptr, ch_size, elm->name); switch(tcv) { case XCT_BOTH: case XCT_OPENING: /* * Process this member. */ ctx->step = edx = n; ctx->phase = 2; break; case XCT_UNKNOWN_OP: case XCT_UNKNOWN_BO: continue; default: n = edx_end; break; /* Phase out */ } break; } if(n != edx_end) continue; } else { ASN_DEBUG("Out of defined members: %d/%d", edx, td->elements_count); } /* It is expected extension */ if(IN_EXTENSION_GROUP(specs, edx + (edx < td->elements_count ? elements[edx].optional : 0))) { ASN_DEBUG("Got anticipated extension at %d", edx); /* * Check for (XCT_BOTH or XCT_UNKNOWN_BO) * By using a mask. Only record a pure * <opening> tags. */ if(tcv & XCT_CLOSING) { /* Found </extension> without body */ } else { ctx->left = 1; ctx->phase = 3; /* Skip ...'s */ } XER_ADVANCE(ch_size); continue; } /* Fall through */ default: break; } ASN_DEBUG("Unexpected XML tag in SEQUENCE [%c%c%c%c%c%c]", size>0?((const char *)buf_ptr)[0]:'.', size>1?((const char *)buf_ptr)[1]:'.', size>2?((const char *)buf_ptr)[2]:'.', size>3?((const char *)buf_ptr)[3]:'.', size>4?((const char *)buf_ptr)[4]:'.', size>5?((const char *)buf_ptr)[5]:'.'); break; } ctx->phase = 4; /* "Phase out" on hard failure */ RETURN(RC_FAIL); }
/* * Generalized function for decoding the primitive values. */ asn_dec_rval_t xer_decode_general(asn_codec_ctx_t *opt_codec_ctx, asn_struct_ctx_t *ctx, /* Type decoder context */ void *struct_key, const char *xml_tag, /* Expected XML tag */ const void *buf_ptr, size_t size, int (*opt_unexpected_tag_decoder) (void *struct_key, const void *chunk_buf, size_t chunk_size), ssize_t (*body_receiver) (void *struct_key, const void *chunk_buf, size_t chunk_size, int have_more) ) { asn_dec_rval_t rval; ssize_t consumed_myself = 0; (void)opt_codec_ctx; /* * Phases of XER/XML processing: * Phase 0: Check that the opening tag matches our expectations. * Phase 1: Processing body and reacting on closing tag. */ if(ctx->phase > 1) RETURN(RC_FAIL); for(;;) { pxer_chunk_type_e ch_type; /* XER chunk type */ ssize_t ch_size; /* Chunk size */ xer_check_tag_e tcv; /* Tag check value */ /* * Get the next part of the XML stream. */ ch_size = xer_next_token(&ctx->context, buf_ptr, size, &ch_type); switch(ch_size) { case -1: RETURN(RC_FAIL); case 0: RETURN(RC_WMORE); default: switch(ch_type) { case PXER_COMMENT: /* Got XML comment */ ADVANCE(ch_size); /* Skip silently */ continue; case PXER_TEXT: if(ctx->phase == 0) { /* * We have to ignore whitespace here, * but in order to be forward compatible * with EXTENDED-XER (EMBED-VALUES, #25) * any text is just ignored here. */ } else { XER_GOT_BODY(buf_ptr, ch_size, size); } ADVANCE(ch_size); continue; case PXER_TAG: break; /* Check the rest down there */ } } assert(ch_type == PXER_TAG && size); tcv = xer_check_tag(buf_ptr, ch_size, xml_tag); /* * Phase 0: * Expecting the opening tag * for the type being processed. * Phase 1: * Waiting for the closing XML tag. */ switch(tcv) { case XCT_BOTH: if(ctx->phase) break; /* Finished decoding of an empty element */ XER_GOT_EMPTY(); ADVANCE(ch_size); ctx->phase = 2; /* Phase out */ RETURN(RC_OK); case XCT_OPENING: if(ctx->phase) break; ADVANCE(ch_size); ctx->phase = 1; /* Processing body phase */ continue; case XCT_CLOSING: if(!ctx->phase) break; ADVANCE(ch_size); ctx->phase = 2; /* Phase out */ RETURN(RC_OK); case XCT_UNKNOWN_BO: /* * Certain tags in the body may be expected. */ if(opt_unexpected_tag_decoder && opt_unexpected_tag_decoder(struct_key, buf_ptr, ch_size) >= 0) { /* Tag's processed fine */ ADVANCE(ch_size); if(!ctx->phase) { /* We are not expecting * the closing tag anymore. */ ctx->phase = 2; /* Phase out */ RETURN(RC_OK); } continue; } /* Fall through */ default: break; /* Unexpected tag */ } ASN_DEBUG("Unexpected XML tag (expected \"%s\")", xml_tag); break; /* Dark and mysterious things have just happened */ } RETURN(RC_FAIL); }
/* * Decode the XER (XML) data. */ asn_dec_rval_t CHOICE_decode_xer(Allocator * allocator, asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td, void **struct_ptr, const char *opt_mname, const void *buf_ptr, size_t size) { /* * Bring closer parts of structure description. */ asn_CHOICE_specifics_t *specs = (asn_CHOICE_specifics_t *)td->specifics; const char *xml_tag = opt_mname ? opt_mname : td->xml_tag; /* * Parts of the structure being constructed. */ void *st = *struct_ptr; /* Target structure. */ asn_struct_ctx_t *ctx; /* Decoder context */ asn_dec_rval_t rval; /* Return value of a decoder */ ssize_t consumed_myself = 0; /* Consumed bytes from ptr */ int edx; /* Element index */ /* * Create the target structure if it is not present already. */ if(st == 0) { st = *struct_ptr = CXX_ALLOC_WRAP CALLOC(1, specs->struct_size); if(st == 0) RETURN(RC_FAIL); } /* * Restore parsing context. */ ctx = (asn_struct_ctx_t *)((char *)st + specs->ctx_offset); if(ctx->phase == 0 && !*xml_tag) ctx->phase = 1; /* Skip the outer tag checking phase */ /* * Phases of XER/XML processing: * Phase 0: Check that the opening tag matches our expectations. * Phase 1: Processing body and reacting on closing tag. * Phase 2: Processing inner type. * Phase 3: Only waiting for closing tag. * Phase 4: Skipping unknown extensions. * Phase 5: PHASED OUT */ for(edx = ctx->step; ctx->phase <= 4;) { pxer_chunk_type_e ch_type; /* XER chunk type */ ssize_t ch_size; /* Chunk size */ xer_check_tag_e tcv; /* Tag check value */ asn_TYPE_member_t *elm; /* * Go inside the member. */ if(ctx->phase == 2) { asn_dec_rval_t tmprval; void *memb_ptr; /* Pointer to the member */ void **memb_ptr2; /* Pointer to that pointer */ elm = &td->elements[edx]; if(elm->flags & ATF_POINTER) { /* Member is a pointer to another structure */ memb_ptr2 = (void **)((char *)st + elm->memb_offset); } else { memb_ptr = (char *)st + elm->memb_offset; memb_ptr2 = &memb_ptr; } /* Start/Continue decoding the inner member */ tmprval = elm->type->xer_decoder(allocator, opt_codec_ctx, elm->type, memb_ptr2, elm->name, buf_ptr, size); XER_ADVANCE(tmprval.consumed); ASN_DEBUG("XER/CHOICE: itdf: [%s] code=%d", elm->type->name, tmprval.code); if(tmprval.code != RC_OK) RETURN(tmprval.code); assert(_fetch_present_idx(st, specs->pres_offset, specs->pres_size) == 0); /* Record what we've got */ _set_present_idx(st, specs->pres_offset, specs->pres_size, edx + 1); ctx->phase = 3; /* Fall through */ } /* No need to wait for closing tag; special mode. */ if(ctx->phase == 3 && !*xml_tag) { ctx->phase = 5; /* Phase out */ RETURN(RC_OK); } /* * Get the next part of the XML stream. */ ch_size = xer_next_token(&ctx->context, buf_ptr, size, &ch_type); switch(ch_size) { case -1: RETURN(RC_FAIL); case 0: RETURN(RC_WMORE); default: switch(ch_type) { case PXER_COMMENT: /* Got XML comment */ case PXER_TEXT: /* Ignore free-standing text */ XER_ADVANCE(ch_size); /* Skip silently */ continue; case PXER_TAG: break; /* Check the rest down there */ } } tcv = xer_check_tag(buf_ptr, ch_size, xml_tag); ASN_DEBUG("XER/CHOICE checked [%c%c%c%c] vs [%s], tcv=%d", ch_size>0?((const uint8_t *)buf_ptr)[0]:'?', ch_size>1?((const uint8_t *)buf_ptr)[1]:'?', ch_size>2?((const uint8_t *)buf_ptr)[2]:'?', ch_size>3?((const uint8_t *)buf_ptr)[3]:'?', xml_tag, tcv); /* Skip the extensions section */ if(ctx->phase == 4) { ASN_DEBUG("skip_unknown(%d, %ld)", tcv, (long)ctx->left); switch(xer_skip_unknown(tcv, &ctx->left)) { case -1: ctx->phase = 5; RETURN(RC_FAIL); continue; case 1: ctx->phase = 3; /* Fall through */ case 0: XER_ADVANCE(ch_size); continue; case 2: ctx->phase = 3; break; } } switch(tcv) { case XCT_BOTH: break; /* No CHOICE? */ case XCT_CLOSING: if(ctx->phase != 3) break; XER_ADVANCE(ch_size); ctx->phase = 5; /* Phase out */ RETURN(RC_OK); case XCT_OPENING: if(ctx->phase == 0) { XER_ADVANCE(ch_size); ctx->phase = 1; /* Processing body phase */ continue; } /* Fall through */ case XCT_UNKNOWN_OP: case XCT_UNKNOWN_BO: if(ctx->phase != 1) break; /* Really unexpected */ /* * Search which inner member corresponds to this tag. */ for(edx = 0; edx < td->elements_count; edx++) { elm = &td->elements[edx]; tcv = xer_check_tag(buf_ptr,ch_size,elm->name); switch(tcv) { case XCT_BOTH: case XCT_OPENING: /* * Process this member. */ ctx->step = edx; ctx->phase = 2; break; case XCT_UNKNOWN_OP: case XCT_UNKNOWN_BO: continue; default: edx = td->elements_count; break; /* Phase out */ } break; } if(edx != td->elements_count) continue; /* It is expected extension */ if(specs->ext_start != -1) { ASN_DEBUG("Got anticipated extension"); /* * Check for (XCT_BOTH or XCT_UNKNOWN_BO) * By using a mask. Only record a pure * <opening> tags. */ if(tcv & XCT_CLOSING) { /* Found </extension> without body */ ctx->phase = 3; /* Terminating */ } else { ctx->left = 1; ctx->phase = 4; /* Skip ...'s */ } XER_ADVANCE(ch_size); continue; } /* Fall through */ default: break; } ASN_DEBUG("Unexpected XML tag [%c%c%c%c] in CHOICE [%s]" " (ph=%d, tag=%s)", ch_size>0?((const uint8_t *)buf_ptr)[0]:'?', ch_size>1?((const uint8_t *)buf_ptr)[1]:'?', ch_size>2?((const uint8_t *)buf_ptr)[2]:'?', ch_size>3?((const uint8_t *)buf_ptr)[3]:'?', td->name, ctx->phase, xml_tag); break; } ctx->phase = 5; /* Phase out, just in case */ RETURN(RC_FAIL); }