| |
| /* |
| * Licensed to the Apache Software Foundation (ASF) under one or more |
| * contributor license agreements. See the NOTICE file distributed with |
| * this work for additional information regarding copyright ownership. |
| * The ASF licenses this file to You under the Apache License, Version 2.0 |
| * (the "License"); you may not use this file except in compliance with |
| * the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| #include <stdio.h> |
| #include <axis2_const.h> |
| #include <axutil_error.h> |
| #include <axutil_utils_defines.h> |
| #include <axutil_utils.h> |
| #include <axutil_env.h> |
| #include <axutil_string.h> |
| #include <axutil_array_list.h> |
| #include <axiom_element.h> |
| #include <axiom_children_iterator.h> |
| #include <axiom_document.h> |
| #include <axiom_comment.h> |
| #include <oxs_constants.h> |
| #include <oxs_c14n.h> |
| #include "c14n_sorted_list.h" |
| |
| #define N_C14N_DEBUG |
| |
| #define DEFAULT_STACK_SIZE 16 |
| #define INIT_BUFFER_SIZE 256 |
| |
| #define c14n_ns_stack_push(save_stack, ctx) \ |
| (save_stack)->head = (ctx)->ns_stack->head; \ |
| (save_stack)->def_ns = (ctx)->ns_stack->def_ns; |
| |
| #define c14n_ns_stack_pop(saved_stack, ctx) \ |
| (ctx)->ns_stack->head = (saved_stack)->head; \ |
| (ctx)->ns_stack->def_ns = (saved_stack)->def_ns; |
| |
| #define c14n_ns_stack_set_default(ns, ctx) \ |
| ((ctx)->ns_stack->def_ns = (ns)) |
| |
| #define c14n_ns_stack_get_default(ctx) \ |
| ((ctx)->ns_stack->def_ns) |
| |
| #define C14N_GET_ROOT_NODE_FROM_DOC_OR_NODE(doc, node, ctx) \ |
| ((doc) ? axiom_document_get_root_element((axiom_document_t *)(doc), \ |
| (ctx)->env) : c14n_get_root_node((node), (ctx))) |
| |
| typedef enum { |
| C14N_XML_C14N = 1, |
| C14N_XML_C14N_WITH_COMMENTS, |
| C14N_XML_EXC_C14N, |
| C14N_XML_EXC_C14N_WITH_COMMENTS, |
| } c14n_algo_t; |
| |
| typedef struct c14n_ns_stack { |
| int head; /*index of the currnt stack TOP*/ |
| int size; /*total size allocated for current stack*/ |
| axiom_namespace_t **stack; /*namespace array*/ |
| axiom_namespace_t *def_ns; /*default ns in current scope*/ |
| } c14n_ns_stack_t; |
| |
| typedef struct c14n_ctx { |
| const axutil_env_t *env; |
| const axiom_document_t *doc; |
| axis2_bool_t comments; |
| axis2_char_t **outbuf; |
| axutil_stream_t *outstream; |
| axis2_bool_t exclusive; |
| axis2_bool_t use_stream; |
| const axutil_array_list_t *ns_prefixes; |
| const axiom_node_t *node; |
| c14n_ns_stack_t *ns_stack; |
| } c14n_ctx_t; |
| |
| /*Function prototypes for ns stack*/ |
| |
| static c14n_ns_stack_t* |
| c14n_ns_stack_create( |
| const c14n_ctx_t *ctx |
| ); |
| |
| static void |
| c14n_ns_stack_free( |
| c14n_ctx_t *ctx |
| ); |
| |
| static axis2_status_t |
| c14n_ns_stack_find( |
| const axiom_namespace_t *ns, |
| const c14n_ctx_t *ctx |
| ); |
| |
| static axis2_status_t |
| c14n_ns_stack_find_with_prefix_uri( |
| const axis2_char_t *prefix, |
| const axis2_char_t *uri, |
| const c14n_ctx_t *ctx |
| ); |
| |
| static axis2_status_t |
| c14n_ns_stack_add( |
| axiom_namespace_t *ns, |
| const c14n_ctx_t *ctx |
| ); |
| |
| /*ns stack implementation*/ |
| |
| static c14n_ns_stack_t* |
| c14n_ns_stack_create( |
| const c14n_ctx_t *ctx) |
| { |
| c14n_ns_stack_t *ns_stack = NULL; |
| |
| ns_stack = (c14n_ns_stack_t *) (AXIS2_MALLOC(ctx->env->allocator, sizeof(c14n_ns_stack_t))); |
| |
| if(ns_stack) |
| { |
| ns_stack->head = 0; |
| ns_stack->size = 0; |
| ns_stack->stack = NULL; |
| ns_stack->def_ns = NULL; |
| } |
| else |
| AXIS2_ERROR_SET(ctx->env->error, AXIS2_ERROR_NO_MEMORY, AXIS2_FAILURE); |
| |
| return ns_stack; |
| } |
| |
| static axis2_status_t c14n_ns_stack_add( |
| axiom_namespace_t *ns, |
| const c14n_ctx_t *ctx) |
| { |
| c14n_ns_stack_t *ns_stack = ctx->ns_stack; |
| |
| if(!ns_stack->stack) |
| { |
| ns_stack->stack = (axiom_namespace_t **) (AXIS2_MALLOC(ctx->env->allocator, |
| sizeof(axiom_namespace_t*) * DEFAULT_STACK_SIZE)); |
| if(!ns_stack->stack) |
| { |
| AXIS2_ERROR_SET(ctx->env->error, AXIS2_ERROR_NO_MEMORY, AXIS2_FAILURE); |
| return AXIS2_FAILURE; |
| } |
| else |
| ns_stack->size = DEFAULT_STACK_SIZE; |
| } |
| else if(ns_stack->head >= ns_stack->size) |
| { |
| int size = 2 * ns_stack->size; |
| axiom_namespace_t **tmp_stack = (axiom_namespace_t **) (AXIS2_MALLOC(ctx->env->allocator, |
| sizeof(axiom_namespace_t*) * size)); |
| if(tmp_stack) |
| { |
| /*int i = 0;*/ |
| /* TODO:DONE use memcpy for this.*/ |
| /*for (i=0; i<ns_stack->size; i++) |
| tmp_stack[i] = (ns_stack->stack)[i];*/ |
| memcpy(tmp_stack, ns_stack, sizeof(axiom_namespace_t*) * ns_stack->size); |
| |
| ns_stack->size = size; |
| |
| AXIS2_FREE(ctx->env->allocator, ns_stack->stack); |
| ns_stack->stack = tmp_stack; |
| } |
| else |
| { |
| AXIS2_ERROR_SET(ctx->env->error, AXIS2_ERROR_NO_MEMORY, AXIS2_FAILURE); |
| return AXIS2_FAILURE; |
| } |
| } |
| |
| /*if memory overflow occur we won't be here*/ |
| (ns_stack->stack)[ns_stack->head] = ns; |
| (ns_stack->head)++; |
| |
| return AXIS2_SUCCESS; |
| } |
| |
| /* |
| * TODO: DONE |
| * Find process should be changed ( if the ns has the same prefix but diff uri) |
| * Eg: <a xmlns:x="a"> |
| * <b xmlns:x="b"> |
| * <c xmlns:x="a"/> |
| * </b> |
| * </a> |
| * */ |
| static axis2_status_t c14n_ns_stack_find_with_prefix_uri( |
| const axis2_char_t *prefix, |
| const axis2_char_t *uri, |
| const c14n_ctx_t *ctx) |
| { |
| int i; |
| c14n_ns_stack_t *ns_stack = ctx->ns_stack; |
| if(ns_stack->stack) /*Is this necessary?*/ |
| { |
| for(i = ns_stack->head - 1; i >= 0; i--) |
| { |
| axis2_char_t *prefix_i = axiom_namespace_get_prefix((ns_stack->stack)[i], ctx->env); |
| |
| if(axutil_strcmp(prefix_i, prefix) == 0) |
| { |
| axis2_char_t *uri_i = axiom_namespace_get_uri((ns_stack->stack)[i], ctx->env); |
| if(axutil_strcmp(uri_i, uri) == 0) |
| return AXIS2_SUCCESS; |
| else |
| return AXIS2_FALSE; |
| } |
| else |
| continue; |
| |
| } |
| } |
| return AXIS2_FAILURE; |
| } |
| |
| static axis2_status_t c14n_ns_stack_find( |
| const axiom_namespace_t *ns, |
| const c14n_ctx_t *ctx) |
| { |
| return (c14n_ns_stack_find_with_prefix_uri(axiom_namespace_get_prefix((axiom_namespace_t *) ns, |
| ctx->env), axiom_namespace_get_uri((axiom_namespace_t *) ns, ctx->env), ctx)); |
| } |
| |
| static void c14n_ns_stack_free( |
| c14n_ctx_t *ctx) |
| { |
| if(ctx->ns_stack->stack) |
| { |
| AXIS2_FREE(ctx->env->allocator, ctx->ns_stack->stack); |
| ctx->ns_stack->stack = NULL; |
| } |
| ctx->ns_stack->stack = NULL; |
| ctx->ns_stack->head = 0; |
| ctx->ns_stack->size = 0; |
| |
| /**/ |
| AXIS2_FREE(ctx->env->allocator, ctx->ns_stack); |
| ctx->ns_stack = NULL; |
| } |
| |
| /* Function Prototypes */ |
| |
| static axis2_status_t |
| c14n_apply_on_element( |
| const axiom_node_t *node, |
| const c14n_ctx_t *ctx); |
| |
| static axis2_status_t |
| c14n_apply_on_namespace_axis( |
| const axiom_element_t *ele, |
| const axiom_node_t *node, |
| const c14n_ctx_t *ctx); |
| |
| static axis2_status_t |
| c14n_apply_on_namespace_axis_exclusive( |
| const axiom_element_t *ele, |
| const axiom_node_t *node, |
| const c14n_ctx_t *ctx); |
| |
| static axis2_status_t |
| c14n_apply_on_attribute_axis( |
| const axiom_element_t *ele, |
| const c14n_ctx_t *ctx); |
| |
| static axis2_status_t |
| c14n_apply_on_node( |
| const axiom_node_t *node, |
| const c14n_ctx_t *ctx); |
| |
| static void |
| c14n_apply_on_comment( |
| const axiom_node_t *node, |
| const c14n_ctx_t *ctx); |
| |
| static void |
| c14n_output( |
| const axis2_char_t *str, |
| const c14n_ctx_t *ctx); |
| |
| static int |
| attr_compare( |
| const void *a1, |
| const void *a2, |
| const void *context); |
| |
| static int |
| ns_prefix_compare( |
| const void *ns1, |
| const void *ns2, |
| const void *context); |
| |
| static int |
| ns_uri_compare( |
| const void *ns1, |
| const void *ns2, |
| const void *context); |
| |
| static axis2_char_t* |
| c14n_normalize_attribute( |
| axis2_char_t *attval, |
| const c14n_ctx_t *ctx); |
| |
| static axis2_char_t* |
| c14n_normalize_text( |
| axis2_char_t *text, |
| const c14n_ctx_t *ctx); |
| |
| static void |
| c14n_apply_on_namespace( |
| const void *ns, |
| const void *ctx); |
| |
| static axis2_bool_t |
| c14n_need_to_declare_ns( |
| const axiom_element_t *ele, |
| const axiom_node_t *node, |
| const axiom_namespace_t *ns, |
| const c14n_ctx_t *ctx); |
| |
| static axis2_bool_t |
| c14n_ns_visibly_utilized( |
| const axiom_element_t *ele, |
| const axiom_node_t *node, |
| const axiom_namespace_t *ns, |
| const c14n_ctx_t *ctx); |
| |
| static axis2_bool_t |
| c14n_no_output_ancestor_uses_prefix( |
| const axiom_element_t *ele, |
| const axiom_node_t *node, |
| const axiom_namespace_t *ns, |
| const c14n_ctx_t *ctx); |
| |
| static axiom_node_t* |
| c14n_get_root_node( |
| const axiom_node_t *node, |
| const c14n_ctx_t *ctx); |
| |
| static c14n_algo_t |
| c14n_get_algorithm( |
| const axis2_char_t* algo); |
| |
| /*static axis2_bool_t |
| c14n_in_nodeset( |
| const axiom_node_t *node, |
| const c14n_ctx_t *ctx |
| ); |
| */ |
| |
| /* Implementations */ |
| |
| static void c14n_ctx_free( |
| c14n_ctx_t *ctx) |
| { |
| if(ctx) |
| { |
| c14n_ns_stack_free(ctx); |
| } |
| |
| AXIS2_FREE(ctx->env->allocator, ctx); |
| } |
| |
| static c14n_ctx_t* |
| c14n_init( |
| const axutil_env_t *env, |
| const axiom_document_t *doc, |
| axis2_bool_t comments, |
| axis2_char_t **outbuf, |
| axutil_stream_t *stream, |
| const axis2_bool_t exclusive, |
| const axutil_array_list_t *ns_prefixes, |
| const axis2_bool_t use_stream, |
| const axiom_node_t *node) |
| { |
| c14n_ctx_t *ctx = (c14n_ctx_t *) (AXIS2_MALLOC(env->allocator, sizeof(c14n_ctx_t))); |
| if(ctx) |
| { |
| ctx->env = env; |
| ctx->doc = doc; |
| ctx->comments = comments; |
| ctx->outbuf = outbuf; |
| ctx->exclusive = exclusive; |
| ctx->ns_prefixes = ns_prefixes; |
| ctx->use_stream = use_stream; |
| ctx->node = node; |
| if(use_stream) |
| ctx->outstream = stream; |
| |
| /*this should come after ctx->env=env*/ |
| ctx->ns_stack = c14n_ns_stack_create(ctx); |
| } |
| else |
| AXIS2_ERROR_SET(env->error, AXIS2_ERROR_NO_MEMORY, AXIS2_FAILURE); |
| |
| return ctx; |
| } |
| |
| /*static axis2_bool_t |
| c14n_in_nodeset( |
| const axiom_node_t *node, |
| const c14n_ctx_t *ctx |
| ) |
| { |
| |
| return AXIS2_SUCCESS; |
| }*/ |
| |
| static axiom_node_t* |
| c14n_get_root_node( |
| const axiom_node_t *node, |
| const c14n_ctx_t *ctx) |
| { |
| const axiom_node_t *parent = NULL; |
| const axiom_node_t *prv_parent = NULL; |
| |
| parent = node; |
| while(parent) |
| { |
| prv_parent = parent; |
| parent = axiom_node_get_parent((axiom_node_t *) parent, ctx->env); |
| } |
| return (axiom_node_t *) prv_parent; |
| } |
| |
| static c14n_algo_t c14n_get_algorithm( |
| const axis2_char_t* algo) |
| { |
| if(axutil_strcmp(algo, OXS_HREF_XML_C14N) == 0) |
| return C14N_XML_C14N; |
| |
| if(axutil_strcmp(algo, OXS_HREF_XML_C14N_WITH_COMMENTS) == 0) |
| return C14N_XML_C14N_WITH_COMMENTS; |
| |
| if(axutil_strcmp(algo, OXS_HREF_XML_EXC_C14N) == 0) |
| return C14N_XML_EXC_C14N; |
| |
| if(axutil_strcmp(algo, OXS_HREF_XML_EXC_C14N_WITH_COMMENTS) == 0) |
| return C14N_XML_EXC_C14N_WITH_COMMENTS; |
| |
| return 0; /*c14n_algo_t enum starts with 1*/ |
| } |
| |
| AXIS2_EXTERN axis2_status_t AXIS2_CALL |
| oxs_c14n_apply_stream_algo( |
| const axutil_env_t *env, |
| const axiom_document_t *doc, |
| axutil_stream_t *stream, |
| const axutil_array_list_t *ns_prefixes, |
| const axiom_node_t *node, |
| const axis2_char_t* algo) |
| { |
| switch(c14n_get_algorithm(algo)) |
| { |
| case C14N_XML_C14N: |
| return oxs_c14n_apply_stream(env, doc, AXIS2_FALSE, stream, AXIS2_FALSE, ns_prefixes, |
| node); |
| case C14N_XML_C14N_WITH_COMMENTS: |
| return oxs_c14n_apply_stream(env, doc, AXIS2_TRUE, stream, AXIS2_FALSE, ns_prefixes, |
| node); |
| case C14N_XML_EXC_C14N: |
| return oxs_c14n_apply_stream(env, doc, AXIS2_FALSE, stream, AXIS2_TRUE, ns_prefixes, |
| node); |
| case C14N_XML_EXC_C14N_WITH_COMMENTS: |
| return oxs_c14n_apply_stream(env, doc, AXIS2_TRUE, stream, AXIS2_TRUE, ns_prefixes, |
| node); |
| default: |
| /*TODO: set the error*/ |
| return AXIS2_FAILURE; |
| } |
| } |
| |
| AXIS2_EXTERN axis2_status_t AXIS2_CALL |
| oxs_c14n_apply_algo( |
| const axutil_env_t *env, |
| const axiom_document_t *doc, |
| axis2_char_t **outbuf, |
| const axutil_array_list_t *ns_prefixes, |
| const axiom_node_t *node, |
| const axis2_char_t *algo) |
| { |
| switch(c14n_get_algorithm(algo)) |
| { |
| case C14N_XML_C14N: |
| return oxs_c14n_apply(env, doc, AXIS2_FALSE, outbuf, AXIS2_FALSE, ns_prefixes, node); |
| case C14N_XML_C14N_WITH_COMMENTS: |
| return oxs_c14n_apply(env, doc, AXIS2_TRUE, outbuf, AXIS2_FALSE, ns_prefixes, node); |
| case C14N_XML_EXC_C14N: |
| return oxs_c14n_apply(env, doc, AXIS2_FALSE, outbuf, AXIS2_TRUE, ns_prefixes, node); |
| case C14N_XML_EXC_C14N_WITH_COMMENTS: |
| return oxs_c14n_apply(env, doc, AXIS2_TRUE, outbuf, AXIS2_TRUE, ns_prefixes, node); |
| default: |
| /*TODO:set the error*/ |
| return AXIS2_FAILURE; |
| } |
| } |
| |
| AXIS2_EXTERN axis2_status_t AXIS2_CALL |
| oxs_c14n_apply_stream( |
| const axutil_env_t *env, |
| const axiom_document_t *doc, |
| axis2_bool_t comments, |
| axutil_stream_t *stream, |
| const axis2_bool_t exclusive, |
| const axutil_array_list_t *ns_prefixes, |
| const axiom_node_t *node) |
| { |
| c14n_ctx_t *ctx = NULL; |
| axiom_node_t *root_node = NULL; |
| axis2_status_t status = AXIS2_SUCCESS; |
| axiom_element_t *root_ele = NULL; |
| /*axiom_children_iterator_t *child_itr = NULL;*/ |
| axutil_stream_t *outstream = NULL; |
| |
| ctx = c14n_init(env, doc, comments, NULL, stream, exclusive, ns_prefixes, AXIS2_TRUE, node); |
| |
| if(ctx && ctx->outstream) |
| { |
| root_node = C14N_GET_ROOT_NODE_FROM_DOC_OR_NODE(doc, node, ctx); |
| /*root_node = axiom_document_get_root_element((axiom_document_t *)doc, |
| ctx->env); */ |
| |
| /* shouldn't the called method's document be const?*/ |
| |
| root_ele = axiom_node_get_data_element(root_node, env); |
| status = c14n_apply_on_node((node ? node |
| : root_node), ctx); |
| |
| if(!status) |
| { |
| axutil_stream_free(ctx->outstream, env); |
| ctx->outstream = NULL; |
| } |
| |
| outstream = ctx->outstream; |
| |
| #ifdef TEST |
| printf("--------------\n"); |
| axiom_namespace_t *ns1 = NULL; |
| axiom_namespace_t *ns2 = NULL; |
| axiom_namespace_t *ns3 = NULL; |
| int i = 0; |
| for (i=0; i<17; i++) |
| { |
| char uri[10], pfx[10]; |
| sprintf(uri, "urn:ns%d", i); |
| sprintf(pfx, "ns%d", i); |
| ns1 = axiom_namespace_create(ctx->env, uri, pfx); |
| c14n_ns_stack_add(ns1, ctx); |
| } |
| for (i=0; i<ctx->ns_stack->head; i++) |
| { |
| ns1 = ctx->ns_stack->stack[i]; |
| printf("%s:%s\n", axiom_namespace_get_prefix(ns1, env), |
| axiom_namespace_get_uri(ns1, env)); |
| } |
| printf("%d\n", ctx->ns_stack->size); |
| |
| ns1 = axiom_namespace_create(ctx->env, "urn:ns0", "ns0"); |
| ns2 = axiom_namespace_create(ctx->env, "urn:ns10", "ns10"); |
| ns3 = axiom_namespace_create(ctx->env, "urn:ns2", "ns3"); |
| |
| if (c14n_ns_stack_find(ns1, ctx)) printf("ns1 found\n"); |
| if (c14n_ns_stack_find(ns2, ctx)) printf("ns2 found\n"); |
| if (c14n_ns_stack_find(ns3, ctx)) printf("ns3 found\n"); |
| #endif |
| |
| c14n_ctx_free(ctx); |
| ctx = NULL; |
| } |
| else |
| { |
| AXIS2_ERROR_SET(env->error, AXIS2_ERROR_NO_MEMORY, AXIS2_FAILURE); |
| |
| if(ctx) |
| { |
| c14n_ctx_free(ctx); |
| ctx = NULL; |
| } |
| status = AXIS2_FAILURE; |
| } |
| |
| return status; |
| } |
| |
| |
| AXIS2_EXTERN axis2_status_t AXIS2_CALL |
| oxs_c14n_apply( |
| const axutil_env_t *env, |
| const axiom_document_t *doc, |
| const axis2_bool_t comments, |
| axis2_char_t **outbuf, |
| const axis2_bool_t exclusive, |
| const axutil_array_list_t *ns_prefixes, |
| const axiom_node_t *node) |
| { |
| axutil_stream_t *stream = axutil_stream_create_basic(env); |
| axis2_status_t ret = oxs_c14n_apply_stream(env, doc, comments, stream, exclusive, ns_prefixes, |
| node); |
| |
| *outbuf = NULL; |
| |
| if(!ret) |
| { |
| return AXIS2_FAILURE; |
| } |
| else |
| { |
| int len = axutil_stream_get_len(stream, env) + 1; |
| if(len > 0) |
| { |
| *outbuf = (axis2_char_t *) (AXIS2_MALLOC(env->allocator, sizeof(axis2_char_t) * len)); |
| axutil_stream_read(stream, env, *outbuf, len); |
| axutil_stream_free(stream, env); |
| stream = NULL; |
| return AXIS2_SUCCESS; |
| } |
| else |
| { |
| axutil_stream_free(stream, env); |
| stream = NULL; |
| return AXIS2_FAILURE; |
| } |
| } |
| } |
| |
| static axis2_status_t c14n_apply_on_text( |
| const axiom_node_t *node, |
| const c14n_ctx_t *ctx) |
| { |
| axiom_text_t *text = NULL; |
| text = (axiom_text_t *) axiom_node_get_data_element((axiom_node_t *) node, ctx->env); |
| |
| if(text) |
| { |
| axis2_char_t *textval = (axis2_char_t*) axiom_text_get_text(text, ctx->env); |
| |
| if(textval) |
| textval = c14n_normalize_text(textval, ctx); |
| else |
| /*should never occur*/ |
| return AXIS2_FAILURE; |
| |
| c14n_output(textval, ctx); |
| if(textval) |
| { |
| AXIS2_FREE(ctx->env->allocator, textval); |
| textval = NULL; |
| } |
| } |
| |
| return AXIS2_SUCCESS; |
| } |
| |
| static axis2_status_t c14n_apply_on_node( |
| const axiom_node_t *node, |
| const c14n_ctx_t *ctx) |
| { |
| /* printf("%d %d %d\n", axiom_node_get_node_type((axiom_node_t *)node, ctx->env), AXIOM_COMMENT, AXIOM_ELEMENT); */ |
| switch(axiom_node_get_node_type((axiom_node_t *) node, ctx->env)) |
| { |
| case AXIOM_ELEMENT: |
| c14n_apply_on_element(node, ctx); |
| break; |
| case AXIOM_TEXT: |
| c14n_apply_on_text(node, ctx); |
| break; |
| case AXIOM_COMMENT: |
| if(ctx->comments) |
| { |
| c14n_apply_on_comment(node, ctx); |
| break; |
| } |
| case AXIOM_DOCTYPE: |
| case AXIOM_PROCESSING_INSTRUCTION: |
| default: |
| ; |
| } |
| |
| return AXIS2_SUCCESS; |
| } |
| |
| static void c14n_apply_on_comment( |
| const axiom_node_t *node, |
| const c14n_ctx_t *ctx) |
| { |
| /*TODO: HACK*/ |
| c14n_output("<!--", ctx); |
| c14n_output(axiom_comment_get_value((axiom_comment_t*) axiom_node_get_data_element( |
| (axiom_node_t*) node, ctx->env), ctx->env), ctx); |
| c14n_output("-->", ctx); |
| } |
| |
| static axis2_status_t c14n_apply_on_element( |
| const axiom_node_t *node, |
| const c14n_ctx_t *ctx) |
| { |
| axis2_status_t res = AXIS2_SUCCESS; |
| axiom_element_t *ele = NULL; |
| axiom_namespace_t *ns = NULL; |
| /*axiom_children_iterator_t *child_itr = NULL;*/ |
| c14n_ns_stack_t *save_stack = NULL; |
| axiom_node_t *child_node = NULL; |
| |
| ele = (axiom_element_t *) axiom_node_get_data_element((axiom_node_t *) node, ctx->env); |
| |
| if(!ele) |
| return AXIS2_FAILURE; /*should it be failure?*/ |
| |
| ns = axiom_element_get_namespace(ele, ctx->env, (axiom_node_t *) node); |
| |
| save_stack = c14n_ns_stack_create(ctx); |
| c14n_ns_stack_push(save_stack, ctx); /*save current ns stack*/ |
| |
| /*print qname*/ |
| c14n_output("<", ctx); |
| |
| if(ns) |
| { |
| axis2_char_t *prefix = axiom_namespace_get_prefix(ns, ctx->env); |
| |
| if(axutil_strlen(prefix) > 0) |
| { |
| c14n_output(prefix, ctx); |
| c14n_output(":", ctx); |
| } |
| } |
| c14n_output(axiom_element_get_localname(ele, ctx->env), ctx); |
| |
| if(ctx->exclusive) |
| res = c14n_apply_on_namespace_axis_exclusive(ele, node, ctx); |
| else |
| res = c14n_apply_on_namespace_axis(ele, node, ctx); |
| |
| /* |
| * edited the code so that the same fn does both exc and non-exc. |
| * have to be careful here! |
| */ |
| |
| if(!res) |
| return res; |
| |
| res = c14n_apply_on_attribute_axis(ele, ctx); |
| |
| if(!res) |
| return res; |
| |
| c14n_output(">", ctx); |
| |
| #ifdef C14N_DEBUG |
| /*c14n_output("\n", ctx);*/ |
| #endif |
| |
| /*process child elements*/ |
| |
| child_node = axiom_node_get_first_child((axiom_node_t *) node, ctx->env); |
| |
| while(child_node) |
| { |
| c14n_apply_on_node(child_node, ctx); |
| child_node = axiom_node_get_next_sibling(child_node, ctx->env); |
| } |
| |
| /*process child elements*/ |
| |
| /*child_itr = AXIOM_ELEMENT_GET_CHILDREN(ele, ctx->env, (axiom_node_t*)node); |
| if (child_itr) |
| { |
| |
| while(axiom_children_iterator_has_next(child_itr, ctx->env)) |
| { |
| axiom_node_t *child_node = NULL; |
| child_node = axiom_children_iterator_next(child_itr, ctx->env); |
| |
| if (child_node) |
| { |
| c14n_apply_on_node(child_node, ctx); |
| } |
| } |
| }*/ |
| |
| /*print qname*/ |
| c14n_output("</", ctx); |
| |
| if(ns) |
| { |
| axis2_char_t *prefix = axiom_namespace_get_prefix(ns, ctx->env); |
| |
| if(axutil_strlen(prefix) > 0) |
| { |
| c14n_output(prefix, ctx); |
| c14n_output(":", ctx); |
| } |
| } |
| c14n_output(axiom_element_get_localname(ele, ctx->env), ctx); |
| |
| c14n_output(">", ctx); |
| |
| c14n_ns_stack_pop(save_stack, ctx); /*restore to previous ns stack */ |
| /*TODO:DONE??? save_stack free*/ |
| /*since save_stack is used just to memorize the head of the stack, |
| * we don't have to worry about freeing its members*/ |
| |
| /**/ |
| AXIS2_FREE(ctx->env->allocator, save_stack); |
| save_stack = NULL; |
| |
| #ifdef C14N_DEBUG |
| /*c14n_output("\n", ctx);*/ |
| #endif |
| |
| return res; |
| } |
| |
| static int ns_uri_compare( |
| const void *ns1, |
| const void *ns2, |
| const void *context) |
| { |
| c14n_ctx_t *ctx = (c14n_ctx_t *) context; |
| |
| if(ns1 == ns2) |
| return 0; |
| if(!ns1) |
| return -1; |
| if(!ns2) |
| return 1; |
| |
| return (axutil_strcmp((const axis2_char_t *) axiom_namespace_get_uri((axiom_namespace_t *) ns1, |
| ctx->env), (const axis2_char_t *) axiom_namespace_get_uri((axiom_namespace_t *) ns2, |
| ctx->env))); |
| } |
| |
| static int ns_prefix_compare( |
| const void *ns1, |
| const void *ns2, |
| const void *context) |
| { |
| c14n_ctx_t *ctx = (c14n_ctx_t *) context; |
| |
| if(ns1 == ns2) |
| return 0; |
| if(!ns1) |
| return -1; |
| if(!ns2) |
| return 1; |
| |
| return (axutil_strcmp((const axis2_char_t *) axiom_namespace_get_prefix( |
| (axiom_namespace_t *) ns1, ctx->env), (const axis2_char_t *) axiom_namespace_get_prefix( |
| (axiom_namespace_t *) ns2, ctx->env))); |
| } |
| |
| static int attr_compare( |
| const void *a1, |
| const void *a2, |
| const void *context) |
| { |
| c14n_ctx_t *ctx = (c14n_ctx_t *) context; |
| axiom_attribute_t *attr1 = NULL; |
| axiom_attribute_t *attr2 = NULL; |
| axiom_namespace_t *ns1 = NULL; |
| axiom_namespace_t *ns2 = NULL; |
| int res; |
| |
| if(a1 == a2) |
| return 0; |
| if(!a1) |
| return -1; |
| if(!a2) |
| return 1; |
| |
| attr1 = (axiom_attribute_t *) a1; |
| attr2 = (axiom_attribute_t *) a2; |
| ns1 = axiom_attribute_get_namespace((axiom_attribute_t *) a1, ctx->env); |
| ns2 = axiom_attribute_get_namespace((axiom_attribute_t *) a2, ctx->env); |
| |
| if(ns1 == ns2) |
| return axutil_strcmp( |
| (const axis2_char_t *) axiom_attribute_get_localname((axiom_attribute_t *) a1, ctx->env), |
| (const axis2_char_t *) axiom_attribute_get_localname((axiom_attribute_t *) a2, ctx->env)); |
| |
| if(!ns1) |
| return -1; |
| if(!ns2) |
| return 1; |
| |
| res = axutil_strcmp(axiom_namespace_get_uri(ns1, ctx->env), axiom_namespace_get_uri(ns2, |
| ctx->env)); |
| |
| if(res == 0) |
| return axutil_strcmp( |
| (const axis2_char_t *) axiom_attribute_get_localname((axiom_attribute_t *) a1, ctx->env), |
| (const axis2_char_t *) axiom_attribute_get_localname((axiom_attribute_t *) a2, ctx->env)); |
| else |
| return res; |
| |
| } |
| |
| static void c14n_apply_on_attribute( |
| const void *attribute, |
| const void *context) |
| { |
| c14n_ctx_t *ctx = (c14n_ctx_t *) context; |
| axiom_attribute_t *attr = (axiom_attribute_t *) attribute; |
| axiom_namespace_t *ns = axiom_attribute_get_namespace(attr, ctx->env); |
| axis2_char_t *attvalue = NULL; |
| |
| c14n_output(" ", ctx); |
| if(ns) |
| { |
| axis2_char_t *prefix = axiom_namespace_get_prefix(ns, ctx->env); |
| |
| if(axutil_strlen(prefix) > 0) |
| { |
| c14n_output(prefix, ctx); |
| c14n_output(":", ctx); |
| } |
| } |
| c14n_output(axiom_attribute_get_localname(attr, ctx->env), ctx); |
| c14n_output("=\"", ctx); |
| |
| /* TODO:DONE Normalize the text before output */ |
| attvalue = axiom_attribute_get_value(attr, ctx->env); |
| attvalue = c14n_normalize_attribute(attvalue, (c14n_ctx_t const *) context); |
| |
| c14n_output(attvalue, ctx); |
| |
| c14n_output("\"", ctx); |
| |
| if(attvalue) |
| { |
| AXIS2_FREE(ctx->env->allocator, attvalue); |
| attvalue = NULL; |
| } |
| } |
| |
| static axis2_status_t c14n_apply_on_attribute_axis( |
| const axiom_element_t *ele, |
| const c14n_ctx_t *ctx) |
| { |
| axutil_hash_t *attr_ht = NULL; |
| axutil_hash_index_t *hi = NULL; |
| c14n_sorted_list_t *attr_list = c14n_sorted_list_create(ctx->env); |
| |
| attr_ht = axiom_element_get_all_attributes((axiom_element_t *) ele, ctx->env); |
| |
| if(attr_ht) |
| { |
| for(hi = axutil_hash_first(attr_ht, ctx->env); hi; hi = axutil_hash_next(ctx->env, hi)) |
| { |
| void *v = NULL; |
| axutil_hash_this(hi, NULL, NULL, &v); |
| |
| if(v) |
| { |
| C14N_SORTED_LIST_INSERT(&attr_list, v, ctx, attr_compare, ctx->env); |
| } |
| } |
| |
| C14N_SORTED_LIST_ITERATE(attr_list, ctx, c14n_apply_on_attribute, ctx->env); |
| } |
| |
| /*TODO:DONE C14N_SORTED_LIST_FREE();*/ |
| C14N_SORTED_LIST_FREE_CONTAINER(attr_list, ctx->env); |
| |
| return AXIS2_SUCCESS; |
| |
| /* TODO: Still need to add the "xml" attrs of the parents in case of doc subsets |
| * and non-exclusive c14n |
| * */ |
| } |
| |
| #if 0 |
| static axis2_char_t* |
| c14n_normalize_text( |
| axis2_char_t *text, |
| const c14n_ctx_t *ctx |
| ) |
| { |
| axis2_char_t *buf = NULL; |
| axis2_char_t *endpivot = NULL; |
| axis2_char_t *p = NULL; |
| axis2_char_t *old = NULL; |
| int bufsz = INIT_BUFFER_SIZE; |
| |
| /* TODO:DONE a better buffer implementation */ |
| buf = (axis2_char_t *)(AXIS2_MALLOC(ctx->env->allocator, |
| (sizeof(axis2_char_t) * bufsz) + 10)); |
| if (!buf) |
| { |
| AXIS2_ERROR_SET(ctx->env->error, AXIS2_ERROR_NO_MEMORY, |
| AXIS2_FAILURE); |
| return buf; |
| } |
| |
| p = buf; |
| endpivot = p + bufsz; |
| |
| old = text; |
| |
| while (*old !='\0') |
| { |
| if (p > endpivot) |
| { |
| int size = bufsz * 2; |
| axis2_char_t *temp_buf = (axis2_char_t *)(AXIS2_MALLOC( |
| ctx->env->allocator, sizeof(axis2_char_t) * size + 10)); |
| |
| if (!temp_buf) |
| { |
| AXIS2_ERROR_SET(ctx->env->error, AXIS2_ERROR_NO_MEMORY, |
| AXIS2_FAILURE); |
| return buf; |
| } |
| |
| memcpy(temp_buf, buf, sizeof(axis2_char_t) * bufsz + 10); |
| |
| p = temp_buf + (p - buf); |
| |
| AXIS2_FREE(ctx->env->allocator, buf); |
| buf = temp_buf; |
| bufsz = size; |
| endpivot = buf + bufsz; |
| } |
| |
| switch (*old) |
| { |
| case '&': |
| *p++ = '&'; |
| *p++ = 'a'; |
| *p++ = 'm'; |
| *p++ = 'p'; |
| *p++ = ';'; |
| break; |
| case '>': |
| *p++ = '&'; |
| *p++ = 'g'; |
| *p++ = 't'; |
| *p++ = ';'; |
| break; |
| case '<': |
| *p++ = '&'; |
| *p++ = 'l'; |
| *p++ = 't'; |
| *p++ = ';'; |
| break; |
| case '\x0D': |
| *p++ = '&'; |
| *p++ = '#'; |
| *p++ = 'x'; |
| *p++ = 'D'; |
| *p++ = ';'; |
| break; |
| default: |
| *p++ = *old; |
| } |
| old ++; |
| } |
| *p++ = '\0'; |
| return buf; |
| } |
| #endif |
| |
| static axis2_char_t* |
| c14n_normalize_text( |
| axis2_char_t *text, |
| const c14n_ctx_t *ctx) |
| { |
| axis2_char_t *buf = NULL; |
| int index = 0; |
| int bufsz = INIT_BUFFER_SIZE; |
| int original_size = axutil_strlen(text); |
| |
| /* TODO:DONE a better buffer implementation */ |
| |
| /* we need atleast the size of original text. worst case is, each character is replaced with |
| * 5 other characters (all the texts are special character). But these special characters are |
| * rare and will occur less than 10% of the time. Hence we can create a buffer with length |
| * max(INIT_BUFFER_SIZE, strlen(text)*1.5).. This will reduce the number of memcpy needed |
| */ |
| if(bufsz < original_size * 1.5) |
| bufsz = original_size * 1.5; |
| |
| buf = (axis2_char_t *) AXIS2_MALLOC(ctx->env->allocator, (sizeof(axis2_char_t) * bufsz)); |
| if(!buf) |
| { |
| AXIS2_ERROR_SET(ctx->env->error, AXIS2_ERROR_NO_MEMORY, AXIS2_FAILURE); |
| return buf; |
| } |
| |
| while(original_size > 0) |
| { |
| size_t i = 0; |
| /* scan buffer until the next special character (&, <, >, \x0D) these need to be escaped, |
| * otherwise XML will not be valid*/ |
| axis2_char_t *pos = (axis2_char_t*) strpbrk(text, "&<>\x0D"); |
| if(pos) |
| { |
| i = pos - text; |
| } |
| else |
| { |
| i = original_size; |
| } |
| |
| /* copy everything until the special character */ |
| if(i > 0) |
| { |
| if(index + i + 6 > bufsz) |
| { |
| /* not enough space to write remaining characters + (5 character resulting |
| * from special character + 1 NULL character). So, have to create a new buffer |
| * and populate */ |
| axis2_char_t *temp_buf = NULL; |
| |
| bufsz *= 2; |
| temp_buf = (axis2_char_t *) AXIS2_MALLOC(ctx->env->allocator, sizeof(axis2_char_t) |
| * bufsz); |
| if(!temp_buf) |
| { |
| AXIS2_ERROR_SET(ctx->env->error, AXIS2_ERROR_NO_MEMORY, AXIS2_FAILURE); |
| return buf; |
| } |
| memcpy(temp_buf, buf, index); |
| AXIS2_FREE(ctx->env->allocator, buf); |
| buf = temp_buf; |
| } |
| |
| memcpy(buf + index, text, i); |
| text += i; |
| index += i; |
| original_size -= i; |
| } |
| |
| /* replace the character with the appropriate sequence */ |
| if(original_size > 0) |
| { |
| switch(text[0]) |
| { |
| case '&': |
| buf[index++] = '&'; |
| buf[index++] = 'a'; |
| buf[index++] = 'm'; |
| buf[index++] = 'p'; |
| buf[index++] = ';'; |
| break; |
| case '>': |
| buf[index++] = '&'; |
| buf[index++] = 'g'; |
| buf[index++] = 't'; |
| buf[index++] = ';'; |
| break; |
| case '<': |
| buf[index++] = '&'; |
| buf[index++] = 'l'; |
| buf[index++] = 't'; |
| buf[index++] = ';'; |
| break; |
| case '\x0D': |
| buf[index++] = '&'; |
| buf[index++] = '#'; |
| buf[index++] = 'x'; |
| buf[index++] = 'D'; |
| buf[index++] = ';'; |
| break; |
| default: |
| ; |
| } |
| |
| ++text; |
| --original_size; |
| } |
| } |
| |
| buf[index] = '\0'; |
| /*printf("buffer [%s]\n", buf);*/ |
| return buf; |
| } |
| |
| static axis2_char_t* |
| c14n_normalize_attribute( |
| axis2_char_t *attval, |
| const c14n_ctx_t *ctx) |
| { |
| axis2_char_t *buf = NULL; |
| axis2_char_t *endpivot = NULL; |
| axis2_char_t *p = NULL; |
| axis2_char_t *old = NULL; |
| int bufsz = INIT_BUFFER_SIZE; |
| |
| /* TODO:DONE a better buffer implementation */ |
| buf = (axis2_char_t *) (AXIS2_MALLOC(ctx->env->allocator, sizeof(axis2_char_t) |
| * INIT_BUFFER_SIZE + 10)); |
| if(!buf) |
| { |
| AXIS2_ERROR_SET(ctx->env->error, AXIS2_ERROR_NO_MEMORY, AXIS2_FAILURE); |
| return buf; |
| } |
| |
| p = buf; |
| endpivot = buf + bufsz; |
| |
| old = attval; |
| |
| while(*old != '\0') |
| { |
| if(p > endpivot) |
| { |
| int size = bufsz * 2; |
| axis2_char_t *temp_buf = (axis2_char_t *) (AXIS2_MALLOC(ctx->env->allocator, |
| sizeof(axis2_char_t) * size + 10)); |
| |
| if(!temp_buf) |
| { |
| AXIS2_ERROR_SET(ctx->env->error, AXIS2_ERROR_NO_MEMORY, AXIS2_FAILURE); |
| return buf; |
| } |
| |
| memcpy(temp_buf, buf, sizeof(axis2_char_t) * bufsz + 10); |
| |
| p = temp_buf + (p - buf); |
| |
| AXIS2_FREE(ctx->env->allocator, buf); |
| buf = temp_buf; |
| bufsz = size; |
| endpivot = buf + bufsz; |
| } |
| |
| switch(*old) |
| { |
| case '&': |
| *p++ = '&'; |
| *p++ = 'a'; |
| *p++ = 'm'; |
| *p++ = 'p'; |
| *p++ = ';'; |
| break; |
| case '<': |
| *p++ = '&'; |
| *p++ = 'l'; |
| *p++ = 't'; |
| *p++ = ';'; |
| break; |
| case '"': |
| *p++ = '&'; |
| *p++ = 'q'; |
| *p++ = 'u'; |
| *p++ = 'o'; |
| *p++ = 't'; |
| *p++ = ';'; |
| break; |
| case '\x09': |
| *p++ = '&'; |
| *p++ = '#'; |
| *p++ = 'x'; |
| *p++ = '9'; |
| *p++ = ';'; |
| break; |
| case '\x0A': |
| *p++ = '&'; |
| *p++ = '#'; |
| *p++ = 'x'; |
| *p++ = 'A'; |
| *p++ = ';'; |
| break; |
| case '\x0D': |
| *p++ = '&'; |
| *p++ = '#'; |
| *p++ = 'x'; |
| *p++ = 'D'; |
| *p++ = ';'; |
| break; |
| default: |
| *p++ = *old; |
| } |
| old++; |
| } |
| *p++ = '\0'; |
| return buf; |
| } |
| |
| static axis2_status_t c14n_apply_on_namespace_axis( |
| const axiom_element_t *ele, |
| const axiom_node_t *node, |
| const c14n_ctx_t *ctx) |
| { |
| axutil_hash_t *ns_ht = NULL; |
| axutil_hash_index_t *hi = NULL; |
| |
| c14n_sorted_list_t *out_list = c14n_sorted_list_create(ctx->env); |
| |
| ns_ht = axiom_element_get_namespaces((axiom_element_t *) ele, ctx->env); |
| |
| if(ns_ht) |
| { |
| for(hi = axutil_hash_first(ns_ht, ctx->env); hi; hi = axutil_hash_next(ctx->env, hi)) |
| { |
| void *v = NULL; |
| axutil_hash_this(hi, NULL, NULL, &v); |
| |
| if(v) |
| { |
| axiom_namespace_t *ns = (axiom_namespace_t *) v; |
| |
| axis2_char_t *pfx = axiom_namespace_get_prefix(ns, ctx->env); |
| axis2_char_t *uri = axiom_namespace_get_uri(ns, ctx->env); |
| |
| if(axutil_strlen(pfx) == 0) |
| { |
| /*process for default namespace*/ |
| /*int nsc = ns_prefix_compare(c14n_ns_stack_get_default(ctx), ns, ctx); |
| int len = axutil_strlen(uri);*/ |
| |
| if(axutil_strlen(uri) == 0) |
| { |
| if(c14n_ns_stack_get_default(ctx) != NULL) |
| { |
| c14n_ns_stack_set_default(ns, ctx); |
| C14N_SORTED_LIST_INSERT(&out_list, (void *) ns, ctx, ns_prefix_compare, |
| ctx->env); |
| } |
| |
| } |
| else |
| { |
| axiom_namespace_t *prev_def = c14n_ns_stack_get_default(ctx); |
| |
| axis2_char_t *prev_def_uri = ((prev_def) ? axiom_namespace_get_uri( |
| prev_def, ctx->env) |
| : NULL); |
| |
| if(!prev_def_uri || axutil_strcmp(prev_def_uri, uri) != 0) |
| { |
| c14n_ns_stack_set_default(ns, ctx); |
| C14N_SORTED_LIST_INSERT(&out_list, (void *) ns, ctx, ns_prefix_compare, |
| ctx->env); |
| } |
| } |
| } |
| else if(!c14n_ns_stack_find(ns, ctx)) |
| { |
| /*non-default namespace*/ |
| c14n_ns_stack_add(ns, ctx); |
| C14N_SORTED_LIST_INSERT(&out_list, (void *) ns, ctx, ns_prefix_compare, |
| ctx->env); |
| } |
| } |
| } |
| } |
| |
| C14N_SORTED_LIST_ITERATE(out_list, ctx, c14n_apply_on_namespace, ctx->env); |
| |
| C14N_SORTED_LIST_FREE_CONTAINER(out_list, ctx->env); |
| |
| /*TODO:DONE C14N_SORTED_LIST_FREE();*/ |
| return AXIS2_SUCCESS; |
| } |
| |
| static axis2_status_t c14n_apply_on_namespace_axis_exclusive( |
| const axiom_element_t *ele, |
| const axiom_node_t *node, |
| const c14n_ctx_t *ctx) |
| { |
| axutil_hash_t *ns_ht = NULL; |
| axutil_hash_index_t *hi = NULL; |
| axiom_node_t *pnode = NULL; |
| axiom_element_t *pele = NULL; |
| axiom_namespace_t *ns = NULL; |
| |
| c14n_sorted_list_t *out_list = c14n_sorted_list_create(ctx->env); |
| |
| pele = (axiom_element_t *) ele; |
| pnode = (axiom_node_t *) node; |
| |
| /*treat the default namespace specially*/ |
| |
| ns = axiom_element_get_namespace(pele, ctx->env, pnode); |
| |
| if(ns) |
| { |
| if(axutil_strlen(axiom_namespace_get_prefix((axiom_namespace_t *) ns, ctx->env)) == 0) |
| { |
| axiom_namespace_t *def_ns = c14n_ns_stack_get_default(ctx); |
| if(def_ns || axutil_strlen(axiom_namespace_get_uri((axiom_namespace_t *) ns, ctx->env)) |
| != 0) |
| { |
| if(ns_uri_compare(ns, def_ns, ctx) != 0) |
| { |
| c14n_ns_stack_set_default(ns, ctx); |
| C14N_SORTED_LIST_INSERT(&out_list, (void *) ns, ctx, ns_prefix_compare, |
| ctx->env); |
| } |
| } |
| } |
| } |
| |
| while(pnode) |
| { |
| pele = axiom_node_get_data_element((axiom_node_t *) pnode, ctx->env); |
| ns_ht = axiom_element_get_namespaces((axiom_element_t *) pele, ctx->env); |
| |
| if(ns_ht) |
| { |
| for(hi = axutil_hash_first(ns_ht, ctx->env); hi; hi = axutil_hash_next(ctx->env, hi)) |
| { |
| void *v = NULL; |
| axutil_hash_this(hi, NULL, NULL, &v); |
| |
| if(v) |
| { |
| axis2_char_t *pfx = NULL; |
| ns = (axiom_namespace_t *) v; |
| |
| pfx = axiom_namespace_get_prefix(ns, ctx->env); |
| /*axis2_char_t *uri = axiom_namespace_get_uri(ns, ctx->env);*/ |
| |
| if(axutil_strlen(pfx) == 0) |
| { |
| /* process for default namespace. |
| * NOTE: This part was taken out of here due to the |
| * search thruogh parent-axis |
| * */ |
| } |
| else if(!c14n_ns_stack_find(ns, ctx)) |
| { |
| /*non-default namespace*/ |
| if(c14n_need_to_declare_ns(ele, node, ns, ctx)) |
| { |
| c14n_ns_stack_add(ns, ctx); |
| C14N_SORTED_LIST_INSERT(&out_list, (void *) ns, ctx, ns_prefix_compare, |
| ctx->env); |
| } |
| } |
| } |
| } |
| } |
| pnode = axiom_node_get_parent((axiom_node_t *) pnode, ctx->env); |
| } /*while*/ |
| C14N_SORTED_LIST_ITERATE(out_list, ctx, c14n_apply_on_namespace, ctx->env); |
| |
| C14N_SORTED_LIST_FREE_CONTAINER(out_list, ctx->env); |
| |
| /*TODO:DONE C14N_SORTED_LIST_FREE();*/ |
| return AXIS2_SUCCESS; |
| } |
| |
| static void c14n_apply_on_namespace( |
| const void *namespace, |
| const void *context) |
| { |
| axiom_namespace_t *ns = (axiom_namespace_t *) namespace; |
| c14n_ctx_t *ctx = (c14n_ctx_t *) context; |
| |
| axis2_char_t *pfx = axiom_namespace_get_prefix(ns, ctx->env); |
| axis2_char_t *uri = axiom_namespace_get_uri(ns, ctx->env); |
| |
| /*c14n_output(" *", ctx); |
| c14n_output(axiom_namespace_to_string(ns, ctx->env), ctx); |
| c14n_output("*", ctx);*/ |
| |
| if(axutil_strlen(pfx) > 0) |
| { |
| c14n_output(" xmlns:", ctx); |
| c14n_output(pfx, ctx); |
| } |
| else |
| c14n_output(" xmlns", ctx); |
| |
| c14n_output("=\"", ctx); |
| |
| if(axutil_strlen(uri) > 0) |
| c14n_output(uri, ctx); |
| c14n_output("\"", ctx); |
| |
| } |
| |
| static void c14n_output( |
| const axis2_char_t *str, |
| const c14n_ctx_t *ctx) |
| { |
| #ifdef C14N_DEBUG |
| printf("%s", str); |
| #else |
| if(ctx->use_stream) |
| { |
| axutil_stream_write(ctx->outstream, ctx->env, str, axutil_strlen(str) |
| * sizeof(axis2_char_t)); |
| } |
| #endif |
| } |
| |
| static axis2_bool_t c14n_need_to_declare_ns( |
| const axiom_element_t *ele, |
| const axiom_node_t *node, |
| const axiom_namespace_t *ns, |
| const c14n_ctx_t *ctx) |
| { |
| axis2_bool_t vu = c14n_ns_visibly_utilized(ele, node, ns, ctx); |
| |
| if(vu || (ctx->ns_prefixes && axutil_array_list_contains( |
| (axutil_array_list_t*) (ctx->ns_prefixes), ctx->env, (void*) (axiom_namespace_get_prefix( |
| (axiom_namespace_t*) ns, ctx->env))))) |
| return c14n_no_output_ancestor_uses_prefix(ele, node, ns, ctx); |
| |
| return AXIS2_FALSE; |
| } |
| |
| static axis2_bool_t c14n_ns_visibly_utilized( |
| const axiom_element_t *ele, |
| const axiom_node_t *node, |
| const axiom_namespace_t *ns, |
| const c14n_ctx_t *ctx) |
| { |
| axis2_bool_t vu = AXIS2_FALSE; |
| axiom_namespace_t *ns_ele = NULL; |
| |
| axis2_char_t *pfx = axiom_namespace_get_prefix((axiom_namespace_t*) ns, ctx->env); |
| axis2_char_t *uri = axiom_namespace_get_uri((axiom_namespace_t *) ns, ctx->env); |
| axis2_char_t *pfx_ele = NULL; |
| axis2_char_t *uri_ele = NULL; |
| ns_ele = axiom_element_get_namespace((axiom_element_t*) ele, ctx->env, (axiom_node_t *) node); |
| |
| if(ns_ele) /* return AXIS2_FALSE; TODO:check */ |
| { |
| pfx_ele = axiom_namespace_get_prefix(ns_ele, ctx->env); |
| uri_ele = axiom_namespace_get_uri(ns_ele, ctx->env); |
| } |
| if((axutil_strcmp(pfx, pfx_ele) == 0) && (axutil_strcmp(uri, uri_ele) == 0)) |
| vu = AXIS2_TRUE; |
| else |
| { |
| axutil_hash_t *attr_ht = |
| axiom_element_get_all_attributes((axiom_element_t *) ele, ctx->env); |
| axutil_hash_index_t *hi = NULL; |
| if(attr_ht) |
| { |
| for(hi = axutil_hash_first(attr_ht, ctx->env); hi; hi = axutil_hash_next(ctx->env, hi)) |
| { |
| void *v = NULL; |
| axutil_hash_this(hi, NULL, NULL, &v); |
| |
| if(v) |
| { |
| axiom_attribute_t *attr = (axiom_attribute_t*) v; |
| axiom_namespace_t *ns_attr = axiom_attribute_get_namespace(attr, ctx->env); |
| axis2_char_t *attr_pfx = NULL; |
| |
| /*if in_nodelist(attr) {*/ |
| if(ns_attr) |
| attr_pfx = axiom_namespace_get_prefix(ns_attr, ctx->env); |
| |
| if(axutil_strcmp(attr_pfx, pfx) == 0) |
| { |
| vu = AXIS2_TRUE; |
| if(ctx->env) |
| AXIS2_FREE(ctx->env->allocator, hi); |
| break; |
| } |
| /*}*/ |
| } |
| } |
| } |
| |
| } |
| |
| return vu; |
| } |
| |
| static axis2_bool_t in_nodeset( |
| const axiom_node_t *node, |
| const c14n_ctx_t *ctx) |
| { |
| axiom_node_t *pnode = NULL; |
| pnode = axiom_node_get_parent((axiom_node_t *) node, ctx->env); |
| |
| while(pnode) |
| { |
| if(ctx->node == pnode) |
| return AXIS2_TRUE; |
| pnode = axiom_node_get_parent((axiom_node_t *) pnode, ctx->env); |
| } |
| |
| return AXIS2_FALSE; |
| } |
| |
| static axis2_bool_t c14n_no_output_ancestor_uses_prefix( |
| const axiom_element_t *ele, |
| const axiom_node_t *node, |
| const axiom_namespace_t *ns, |
| const c14n_ctx_t *ctx) |
| { |
| axis2_char_t *pfx = axiom_namespace_get_prefix((axiom_namespace_t*) ns, ctx->env); |
| axis2_char_t *uri = axiom_namespace_get_uri((axiom_namespace_t *) ns, ctx->env); |
| |
| axiom_node_t *parent_node = axiom_node_get_parent((axiom_node_t *) node, ctx->env); |
| axiom_element_t *parent_element = NULL; |
| axiom_namespace_t *parent_ns = NULL; |
| axis2_char_t *parent_pfx = NULL; |
| axis2_char_t *parent_uri = NULL; |
| |
| /* assuming the parent of an element is always an element node in AXIOM*/ |
| while(parent_node) |
| { |
| axutil_hash_index_t *hi = NULL; |
| axutil_hash_t *attr_ht = NULL; |
| |
| /* TODO: |
| * HACK: since we only use a single node as the subset |
| * the following hack should work instead of a more |
| * general in_nodest()*/ |
| |
| if(!in_nodeset(parent_node, ctx)) |
| { |
| /*we reached a node beyond the nodeset, |
| * so the prefix is not used*/ |
| return AXIS2_TRUE; |
| } |
| |
| /* if (in_nodeset(parent)){*/ |
| parent_element = axiom_node_get_data_element((axiom_node_t *) parent_node, ctx->env); |
| parent_ns = axiom_element_get_namespace((axiom_element_t *) parent_element, ctx->env, |
| (axiom_node_t *) parent_node); |
| |
| if(parent_ns) |
| { |
| parent_pfx = axiom_namespace_get_prefix((axiom_namespace_t *) parent_ns, ctx->env); |
| if(axutil_strcmp(pfx, parent_pfx) == 0) |
| { |
| parent_uri = axiom_namespace_get_uri((axiom_namespace_t*) parent_ns, ctx->env); |
| return (!(axutil_strcmp(uri, parent_uri) == 0)); |
| } |
| } |
| |
| attr_ht = axiom_element_get_all_attributes((axiom_element_t *) parent_element, ctx->env); |
| if(attr_ht) |
| { |
| for(hi = axutil_hash_first(attr_ht, ctx->env); hi; hi = axutil_hash_next(ctx->env, hi)) |
| { |
| void *v = NULL; |
| axutil_hash_this(hi, NULL, NULL, &v); |
| |
| if(v) |
| { |
| axiom_attribute_t *attr = (axiom_attribute_t*) v; |
| axiom_namespace_t *attr_ns = axiom_attribute_get_namespace(attr, ctx->env); |
| axis2_char_t *attr_pfx = NULL; |
| axis2_char_t *attr_uri = NULL; |
| |
| if(attr_ns) |
| { |
| attr_pfx = axiom_namespace_get_prefix(attr_ns, ctx->env); |
| attr_uri = axiom_namespace_get_uri(attr_ns, ctx->env); |
| |
| if(axutil_strcmp(attr_pfx, pfx) == 0) |
| return (!(axutil_strcmp(attr_uri, uri) == 0)); |
| /*test for this case*/ |
| } |
| } |
| } |
| } |
| /*}*/ |
| parent_node = axiom_node_get_parent((axiom_node_t *) parent_node, ctx->env); |
| } |
| |
| return AXIS2_TRUE; |
| } |