| /* |
| * 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 <axutil_utils.h> |
| #include <stdlib.h> |
| #include <axutil_string.h> |
| #include <string.h> |
| #include <platforms/axutil_platform_auto_sense.h> |
| |
| AXIS2_EXPORT axis2_char_t *axis2_request_url_prefix = "services"; |
| |
| AXIS2_EXTERN axis2_status_t AXIS2_CALL |
| axutil_parse_rest_url_for_params( |
| const axutil_env_t *env, |
| const axis2_char_t *tmpl, |
| const axis2_char_t *url, |
| int *match_count, |
| axis2_char_t ****matches) |
| { |
| axis2_char_t ***ret = NULL; |
| axis2_char_t *tmp1 = NULL; |
| axis2_char_t **tmp2 = NULL; |
| axis2_char_t ***tmp3 = NULL; |
| axis2_char_t *tmp4 = NULL; |
| axis2_char_t *resource = NULL; |
| axis2_char_t *query = NULL; |
| axis2_char_t *url_tmp = NULL; |
| axis2_char_t *url_resource = NULL; |
| axis2_char_t *url_query = NULL; |
| axis2_bool_t finished = AXIS2_FALSE; |
| axis2_status_t status = AXIS2_FAILURE; |
| int ret_count = 0; |
| int i = 0; |
| int j = 0; |
| axis2_bool_t in_tok = AXIS2_FALSE; |
| |
| tmp2 = AXIS2_MALLOC(env->allocator, 2 * (sizeof(axis2_char_t *))); |
| memset(tmp2, 0, 2 * sizeof(axis2_char_t *)); |
| |
| if(tmpl[0] == '/') |
| { |
| tmp1 = (axis2_char_t *)tmpl; |
| tmp1++; |
| resource = axutil_strdup(env, tmp1); |
| } |
| else |
| { |
| resource = axutil_strdup(env, tmpl); |
| } |
| i = (int)strlen(resource); |
| /* We are sure that the difference lies within the int range */ |
| if(resource[i] == '/') |
| { |
| resource[i] = '\0'; |
| } |
| tmp1 = strchr(resource, '?'); |
| if(tmp1) |
| { |
| axis2_char_t *tmp4 = NULL; |
| |
| tmp4 = tmp1; |
| tmp1++; |
| resource[tmp4 - resource] = '\0'; |
| if(*tmp1 && ((tmp1 - resource) < (int)strlen(resource) - 1)) |
| /* We are sure that the difference lies within the int range */ |
| { |
| query = tmp1; |
| /* |
| * Query String based matching is not implemented. This is |
| * reserved for future implementations. |
| */ |
| } |
| } |
| |
| /* Validation of Template */ |
| i = (int)strlen(resource); |
| /* We are sure that the difference lies within the int range */ |
| |
| if(!strchr(resource, '{') && !strchr(resource, '}')) |
| { |
| i = 0; |
| } |
| for(j = 0; j < i; j++) |
| { |
| if(!in_tok) |
| { |
| if(resource[j] == '}') |
| { |
| AXIS2_FREE(env->allocator, resource); |
| return AXIS2_FAILURE; |
| } |
| else if(resource[j] == '{') |
| { |
| if(j + 1 == i || resource[j + 1] == '}') |
| { |
| AXIS2_FREE(env->allocator, resource); |
| return AXIS2_FAILURE; |
| } |
| else if(resource[j + 1] == '{') |
| { |
| j++; |
| } |
| else |
| { |
| in_tok = AXIS2_TRUE; |
| } |
| } |
| } |
| else |
| { |
| if(resource[j] == '{') |
| { |
| AXIS2_FREE(env->allocator, resource); |
| return AXIS2_FAILURE; |
| } |
| else if(resource[j] == '}') |
| { |
| if(j + 1 < i && resource[j + 1] == '}') |
| { |
| j++; |
| } |
| else |
| { |
| in_tok = AXIS2_FALSE; |
| } |
| } |
| } |
| } |
| if(in_tok) |
| { |
| AXIS2_FREE(env->allocator, resource); |
| return AXIS2_FAILURE; |
| } |
| |
| /* Validity of template guaranteed if not returned */ |
| |
| if(url[0] == '/') |
| { |
| tmp1 = (axis2_char_t *)url; |
| tmp1++; |
| url_resource = axutil_strdup(env, tmp1); |
| } |
| else |
| { |
| url_resource = axutil_strdup(env, url); |
| } |
| i = (int)strlen(url_resource); |
| |
| /* We are sure that the difference lies within the int range */ |
| |
| if(url_resource[i] == '/') |
| { |
| url_resource[i] = '\0'; |
| } |
| i = 0; |
| url_tmp = url_resource; |
| tmp1 = strchr(url_resource, '?'); |
| if(tmp1) |
| { |
| axis2_char_t *tmp4 = NULL; |
| |
| tmp4 = tmp1; |
| tmp1++; |
| url_resource[tmp4 - url_resource] = '\0'; |
| if(*tmp1 && ((tmp1 - url_resource) < (int)strlen(url_resource) - 1)) |
| /* We are sure that the difference lies within the int range */ |
| { |
| url_query = tmp1; |
| } |
| } |
| tmp1 = resource; |
| |
| /* Simplest case match */ |
| |
| if(!strchr(resource, '{')) |
| { |
| if(strcmp(resource, url_resource) == 0) |
| { |
| finished = AXIS2_TRUE; |
| } |
| } |
| |
| while(!finished) |
| { |
| tmp4 = strchr(tmp1, '{'); |
| if(tmp4 && tmp4[1]) |
| { |
| if(tmp4[1] != '{') |
| { |
| axis2_char_t *tmp5 = NULL; |
| axis2_char_t *tmp6 = NULL; |
| axis2_char_t *tmp7 = NULL; |
| axis2_char_t *tmp8 = NULL; |
| axis2_char_t *tmp9 = NULL; |
| |
| /* Logic for finding out constant portion to match */ |
| i = (int)(tmp4 - tmp1); |
| tmp2[0] = AXIS2_MALLOC(env->allocator, (i + 1) * sizeof(char)); |
| strncpy(tmp2[0], tmp1, i); |
| tmp2[0][i] = '\0'; |
| if(url_tmp && *url_tmp) |
| { |
| tmp6 = url_tmp; |
| tmp5 = strstr(tmp6, tmp2[0]); |
| if(tmp5) |
| { |
| tmp5 += strlen(tmp2[0]); |
| tmp7 = tmp4; |
| tmp8 = tmp4; |
| tmp7++; |
| if(*tmp7) |
| { |
| axis2_bool_t finished_tmp = AXIS2_FALSE; |
| while(!finished_tmp) |
| { |
| tmp6 = strchr(tmp8, '}'); |
| if(tmp6 && *tmp6) |
| { |
| if(tmp6[1] != '}') |
| { |
| tmp8 = tmp6 + 1; |
| break; |
| } |
| } |
| else |
| { |
| finished_tmp = AXIS2_TRUE; |
| } |
| } |
| if(!finished_tmp && !strchr(tmp8, '{')) |
| { |
| tmp7 = tmp8 + strlen(tmp8); |
| } |
| else |
| { |
| while(!finished_tmp) |
| { |
| tmp6 = strchr(tmp8, '{'); |
| if(tmp6 && tmp6[1]) |
| { |
| if(tmp6[1] != '{') |
| { |
| tmp7 = tmp6; |
| break; |
| } |
| } |
| else |
| { |
| finished_tmp = AXIS2_TRUE; |
| } |
| } |
| } |
| if(!finished_tmp) |
| { |
| i = (int)(tmp7 - tmp8); |
| tmp9 = AXIS2_MALLOC(env->allocator, (i + 1) * sizeof(char)); |
| strncpy(tmp9, tmp8, i); |
| tmp9[i] = '\0'; |
| } |
| } |
| if(tmp9 && *tmp9) |
| { |
| tmp6 = strstr(tmp5, tmp9); |
| AXIS2_FREE(env->allocator, tmp9); |
| tmp9 = NULL; |
| } |
| else |
| { |
| tmp6 = strchr(tmp5, '/'); |
| } |
| /* Logic for saving the match */ |
| if(tmp6 && tmp6 != tmp5) |
| { |
| i = (int)(tmp6 - tmp5); |
| url_tmp = tmp6; |
| tmp2[1] = AXIS2_MALLOC(env->allocator, (i + 1) * sizeof(char)); |
| strncpy(tmp2[1], tmp5, i); |
| tmp2[1][i] = '\0'; |
| } |
| else |
| { |
| i = (int)strlen(tmp5); |
| /* We are sure that the difference lies within the int range */ |
| tmp2[1] = AXIS2_MALLOC(env->allocator, (i + 1) * sizeof(char)); |
| strncpy(tmp2[1], tmp5, i); |
| tmp2[1][i] = '\0'; |
| url_tmp = NULL; |
| } |
| } |
| } |
| else |
| { |
| break; |
| } |
| while(!finished) |
| { |
| tmp1 = tmp4 + 1; |
| tmp4 = strchr(tmp1, '}'); |
| if(tmp4 && *tmp4) |
| { |
| if(tmp4[1] != '}') |
| { |
| /* Logic for saving the key for the match */ |
| i = (int)(tmp4 - tmp1); |
| if(tmp2[0]) |
| { |
| AXIS2_FREE(env->allocator, tmp2[0]); |
| } |
| tmp2[0] = AXIS2_MALLOC(env->allocator, (i + 1) * sizeof(char)); |
| strncpy(tmp2[0], tmp1, i); |
| tmp2[0][i] = '\0'; |
| tmp3 = ret; |
| ret_count++; |
| ret = AXIS2_MALLOC(env->allocator, ret_count * 2 |
| * (sizeof(axis2_char_t *))); |
| memset(ret, 0, ret_count * 2 * sizeof(axis2_char_t *)); |
| for(i = 0; i < ret_count - 1; i++) |
| { |
| ret[i] = tmp3[i]; |
| } |
| ret[i] = tmp2; |
| tmp2 = AXIS2_MALLOC(env->allocator, 2 * (sizeof(axis2_char_t *))); |
| memset(tmp2, 0, 2 * sizeof(axis2_char_t *)); |
| tmp3 = NULL; |
| break; |
| } |
| else |
| { |
| tmp4++; |
| } |
| } |
| else |
| { |
| finished = AXIS2_TRUE; |
| } |
| } |
| } |
| else |
| { |
| tmp4++; |
| } |
| } |
| else |
| { |
| /* Result of mismatch at the simplest case */ |
| if(!strchr(resource, '{')) |
| { |
| finished = AXIS2_FALSE; |
| break; |
| } |
| finished = AXIS2_TRUE; |
| } |
| tmp1 = tmp4 + 1; |
| } |
| if(resource) |
| { |
| AXIS2_FREE(env->allocator, resource); |
| } |
| if(url_resource) |
| { |
| AXIS2_FREE(env->allocator, url_resource); |
| } |
| if(tmp2) |
| { |
| if(tmp2[0]) |
| { |
| AXIS2_FREE(env->allocator, tmp2[0]); |
| } |
| if(tmp2[1]) |
| { |
| AXIS2_FREE(env->allocator, tmp2[1]); |
| } |
| AXIS2_FREE(env->allocator, tmp2); |
| } |
| if(finished) |
| { |
| status = AXIS2_SUCCESS; |
| } |
| *match_count = ret_count; |
| *matches = ret; |
| return status; |
| } |
| |
| AXIS2_EXTERN axis2_char_t **AXIS2_CALL |
| axutil_parse_request_url_for_svc_and_op( |
| const axutil_env_t *env, |
| const axis2_char_t *request) |
| { |
| axis2_char_t **ret = NULL; |
| axis2_char_t *service_str = NULL; |
| axis2_char_t *tmp = NULL; |
| int i = 0; |
| ret = AXIS2_MALLOC(env->allocator, 2 * (sizeof(axis2_char_t *))); |
| memset(ret, 0, 2 * sizeof(axis2_char_t *)); |
| tmp = (axis2_char_t *)request; |
| |
| tmp = strstr(tmp, axis2_request_url_prefix); |
| if(tmp) |
| { |
| service_str = tmp; |
| tmp += axutil_strlen(axis2_request_url_prefix); |
| /*break stop on first prefix as user may have prefix in service name */ |
| } |
| if(service_str) |
| { |
| service_str += axutil_strlen(axis2_request_url_prefix); |
| if('\0' != *service_str) |
| { |
| if(*service_str == '/') |
| service_str++; /*to remove the leading '/' */ |
| tmp = strchr(service_str, '/'); |
| if(tmp) |
| { |
| i = (int)(tmp - service_str); |
| ret[0] = AXIS2_MALLOC(env->allocator, i * sizeof(char) + 1); |
| strncpy(ret[0], service_str, i); |
| ret[0][i] = '\0'; |
| |
| /* Now search for the op */ |
| service_str = tmp; |
| if('\0' != *service_str) |
| { |
| service_str++; |
| tmp = strchr(service_str, '?'); |
| if(tmp) |
| { |
| i = (int)(tmp - service_str); |
| ret[1] = AXIS2_MALLOC(env->allocator, i * sizeof(char) + 1); |
| strncpy(ret[1], service_str, i); |
| ret[1][i] = '\0'; |
| } |
| else |
| { |
| ret[1] = axutil_strdup(env, service_str); |
| } |
| } |
| } |
| else |
| { |
| ret[0] = axutil_strdup(env, service_str); |
| } |
| } |
| } |
| return ret; |
| } |
| |
| AXIS2_EXTERN axis2_char_t *AXIS2_CALL |
| axutil_xml_quote_string( |
| const axutil_env_t *env, |
| const axis2_char_t *s, |
| axis2_bool_t quotes) |
| { |
| const char *scan; |
| size_t len = 0; |
| size_t extra = 0; |
| char *qstr; |
| char *qscan; |
| char c; |
| |
| for(scan = s; (c = *scan) != '\0'; ++scan, ++len) |
| { |
| if(c == '<' || c == '>') |
| extra += 3; /* < or > */ |
| else if(c == '&') |
| extra += 4; /* & */ |
| else if(quotes && c == '"') |
| extra += 5; /* " */ |
| } |
| |
| /* nothing to do */ |
| if(extra == 0) |
| return NULL; |
| |
| qstr = AXIS2_MALLOC(env->allocator, len + extra + 1); |
| for(scan = s, qscan = qstr; (c = *scan) != '\0'; ++scan) |
| { |
| if(c == '<') |
| { |
| *qscan++ = '&'; |
| *qscan++ = 'l'; |
| *qscan++ = 't'; |
| *qscan++ = ';'; |
| } |
| else if(c == '>') |
| { |
| *qscan++ = '&'; |
| *qscan++ = 'g'; |
| *qscan++ = 't'; |
| *qscan++ = ';'; |
| } |
| else if(c == '&') |
| { |
| *qscan++ = '&'; |
| *qscan++ = 'a'; |
| *qscan++ = 'm'; |
| *qscan++ = 'p'; |
| *qscan++ = ';'; |
| } |
| else if(quotes && c == '"') |
| { |
| *qscan++ = '&'; |
| *qscan++ = 'q'; |
| *qscan++ = 'u'; |
| *qscan++ = 'o'; |
| *qscan++ = 't'; |
| *qscan++ = ';'; |
| } |
| else |
| { |
| *qscan++ = c; |
| } |
| } |
| |
| *qscan = '\0'; |
| return qstr; |
| } |
| |
| AXIS2_EXTERN axis2_status_t AXIS2_CALL |
| axutil_url_decode( |
| const axutil_env_t *env, |
| axis2_char_t *dest, |
| axis2_char_t *src) |
| { |
| AXIS2_PARAM_CHECK(env->error, dest, AXIS2_FAILURE); |
| AXIS2_PARAM_CHECK(env->error, src, AXIS2_FAILURE); |
| |
| for(; *src != '\0'; ++dest, ++src) |
| { |
| if(src[0] == '%' && isxdigit(src[1]) && isxdigit(src[2])) |
| { |
| *dest = (axis2_char_t)(axutil_hexit(src[1]) * 16 + axutil_hexit(src[2])); |
| /* We are sure that the conversion is safe */ |
| src += 2; |
| } |
| else |
| { |
| *dest = *src; |
| } |
| } |
| *dest = '\0'; |
| |
| return AXIS2_SUCCESS; |
| } |
| |
| AXIS2_EXTERN int AXIS2_CALL |
| axutil_hexit( |
| axis2_char_t c) |
| { |
| if(c >= '0' && c <= '9') |
| { |
| return c - '0'; |
| } |
| if(c >= 'a' && c <= 'f') |
| { |
| return c - 'a' + 10; |
| } |
| if(c >= 'A' && c <= 'F') |
| { |
| return c - 'A' + 10; |
| } |
| return 0; |
| } |
| |
| AXIS2_EXTERN axis2_status_t AXIS2_CALL |
| axis2_char_2_byte( |
| const axutil_env_t *env, |
| axis2_char_t *char_buffer, |
| axis2_byte_t **byte_buffer, |
| int *byte_buffer_size) |
| { |
| int length = 0; |
| int i = 0; |
| axis2_byte_t *bytes = NULL; |
| |
| length = (int)axutil_strlen(char_buffer); |
| bytes = (axis2_byte_t *)AXIS2_MALLOC(env->allocator, length * sizeof(axis2_byte_t)); |
| |
| if(!bytes) |
| { |
| AXIS2_ERROR_SET(env->error, AXIS2_ERROR_NO_MEMORY, AXIS2_FAILURE); |
| AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, "No memory. Cannot create byte buffer"); |
| return AXIS2_FAILURE; |
| } |
| |
| for(i = 0; i < length; i++) |
| { |
| bytes[i] = (axis2_byte_t)char_buffer[i]; |
| } |
| *byte_buffer = bytes; |
| *byte_buffer_size = length; |
| return AXIS2_SUCCESS; |
| } |
| |