pick up wakaama files from https://github.com/eclipse/wakaama
Diff: core/uri.c
- Revision:
- 0:1fa43ab66921
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/core/uri.c Wed Apr 19 11:30:02 2017 +0000 @@ -0,0 +1,329 @@ +/******************************************************************************* + * + * Copyright (c) 2013, 2014 Intel Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * and Eclipse Distribution License v1.0 which accompany this distribution. + * + * The Eclipse Public License is available at + * http://www.eclipse.org/legal/epl-v10.html + * The Eclipse Distribution License is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + * + * Contributors: + * David Navarro, Intel Corporation - initial API and implementation + * Fabien Fleutot - Please refer to git log + * Toby Jaffey - Please refer to git log + * Bosch Software Innovations GmbH - Please refer to git log + * Pascal Rieux - Please refer to git log + * + *******************************************************************************/ + +/* + Copyright (c) 2013, 2014 Intel Corporation + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + THE POSSIBILITY OF SUCH DAMAGE. + + David Navarro <david.navarro@intel.com> + +*/ + +#include "internals.h" +#include <stdlib.h> +#include <string.h> +#include <ctype.h> + + +static int prv_parseNumber(uint8_t * uriString, + size_t uriLength, + size_t * headP) +{ + int result = 0; + + if (uriString[*headP] == '/') + { + // empty Object Instance ID with resource ID is not allowed + return -1; + } + while (*headP < uriLength && uriString[*headP] != '/') + { + if ('0' <= uriString[*headP] && uriString[*headP] <= '9') + { + result += uriString[*headP] - '0'; + result *= 10; + } + else + { + return -1; + } + *headP += 1; + } + + result /= 10; + return result; +} + + +int uri_getNumber(uint8_t * uriString, + size_t uriLength) +{ + size_t index = 0; + + return prv_parseNumber(uriString, uriLength, &index); +} + + +lwm2m_uri_t * uri_decode(char * altPath, + multi_option_t *uriPath) +{ + lwm2m_uri_t * uriP; + int readNum; + + LOG_ARG("altPath: \"%s\"", altPath); + + uriP = (lwm2m_uri_t *)lwm2m_malloc(sizeof(lwm2m_uri_t)); + if (NULL == uriP) return NULL; + + memset(uriP, 0, sizeof(lwm2m_uri_t)); + + // Read object ID + if (NULL != uriPath + && URI_REGISTRATION_SEGMENT_LEN == uriPath->len + && 0 == strncmp(URI_REGISTRATION_SEGMENT, (char *)uriPath->data, uriPath->len)) + { + uriP->flag |= LWM2M_URI_FLAG_REGISTRATION; + uriPath = uriPath->next; + if (uriPath == NULL) return uriP; + } + else if (NULL != uriPath + && URI_BOOTSTRAP_SEGMENT_LEN == uriPath->len + && 0 == strncmp(URI_BOOTSTRAP_SEGMENT, (char *)uriPath->data, uriPath->len)) + { + uriP->flag |= LWM2M_URI_FLAG_BOOTSTRAP; + uriPath = uriPath->next; + if (uriPath != NULL) goto error; + return uriP; + } + + if ((uriP->flag & LWM2M_URI_MASK_TYPE) != LWM2M_URI_FLAG_REGISTRATION) + { + // Read altPath if any + if (altPath != NULL) + { + int i; + if (NULL == uriPath) + { + lwm2m_free(uriP); + return NULL; + } + for (i = 0 ; i < uriPath->len ; i++) + { + if (uriPath->data[i] != altPath[i+1]) + { + lwm2m_free(uriP); + return NULL; + } + } + uriPath = uriPath->next; + } + if (NULL == uriPath || uriPath->len == 0) + { + uriP->flag |= LWM2M_URI_FLAG_DELETE_ALL; + return uriP; + } + } + + readNum = uri_getNumber(uriPath->data, uriPath->len); + if (readNum < 0 || readNum > LWM2M_MAX_ID) goto error; + uriP->objectId = (uint16_t)readNum; + uriP->flag |= LWM2M_URI_FLAG_OBJECT_ID; + uriPath = uriPath->next; + + if ((uriP->flag & LWM2M_URI_MASK_TYPE) == LWM2M_URI_FLAG_REGISTRATION) + { + if (uriPath != NULL) goto error; + return uriP; + } + uriP->flag |= LWM2M_URI_FLAG_DM; + + if (uriPath == NULL) return uriP; + + // Read object instance + if (uriPath->len != 0) + { + readNum = uri_getNumber(uriPath->data, uriPath->len); + if (readNum < 0 || readNum >= LWM2M_MAX_ID) goto error; + uriP->instanceId = (uint16_t)readNum; + uriP->flag |= LWM2M_URI_FLAG_INSTANCE_ID; + } + uriPath = uriPath->next; + + if (uriPath == NULL) return uriP; + + // Read resource ID + if (uriPath->len != 0) + { + // resource ID without an instance ID is not allowed + if ((uriP->flag & LWM2M_URI_FLAG_INSTANCE_ID) == 0) goto error; + + readNum = uri_getNumber(uriPath->data, uriPath->len); + if (readNum < 0 || readNum > LWM2M_MAX_ID) goto error; + uriP->resourceId = (uint16_t)readNum; + uriP->flag |= LWM2M_URI_FLAG_RESOURCE_ID; + } + + // must be the last segment + if (NULL == uriPath->next) + { + LOG_URI(uriP); + return uriP; + } + +error: + LOG("Exiting on error"); + lwm2m_free(uriP); + return NULL; +} + +int lwm2m_stringToUri(const char * buffer, + size_t buffer_len, + lwm2m_uri_t * uriP) +{ + size_t head; + int readNum; + + LOG_ARG("buffer_len: %u, buffer: \"%.*s\"", buffer_len, buffer_len, buffer); + + if (buffer == NULL || buffer_len == 0 || uriP == NULL) return 0; + + memset(uriP, 0, sizeof(lwm2m_uri_t)); + + // Skip any white space + head = 0; + while (head < buffer_len && isspace(buffer[head]&0xFF)) + { + head++; + } + if (head == buffer_len) return 0; + + // Check the URI start with a '/' + if (buffer[head] != '/') return 0; + head++; + if (head == buffer_len) return 0; + + // Read object ID + readNum = prv_parseNumber((uint8_t *)buffer, buffer_len, &head); + if (readNum < 0 || readNum > LWM2M_MAX_ID) return 0; + uriP->objectId = (uint16_t)readNum; + uriP->flag |= LWM2M_URI_FLAG_OBJECT_ID; + + if (buffer[head] == '/') head += 1; + if (head >= buffer_len) + { + LOG_ARG("Parsed characters: %u", head); + LOG_URI(uriP); + return head; + } + + readNum = prv_parseNumber((uint8_t *)buffer, buffer_len, &head); + if (readNum < 0 || readNum >= LWM2M_MAX_ID) return 0; + uriP->instanceId = (uint16_t)readNum; + uriP->flag |= LWM2M_URI_FLAG_INSTANCE_ID; + + if (buffer[head] == '/') head += 1; + if (head >= buffer_len) + { + LOG_ARG("Parsed characters: %u", head); + LOG_URI(uriP); + return head; + } + + readNum = prv_parseNumber((uint8_t *)buffer, buffer_len, &head); + if (readNum < 0 || readNum >= LWM2M_MAX_ID) return 0; + uriP->resourceId = (uint16_t)readNum; + uriP->flag |= LWM2M_URI_FLAG_RESOURCE_ID; + + if (head != buffer_len) return 0; + + LOG_ARG("Parsed characters: %u", head); + LOG_URI(uriP); + + return head; +} + +int uri_toString(lwm2m_uri_t * uriP, + uint8_t * buffer, + size_t bufferLen, + uri_depth_t * depthP) +{ + size_t head; + int res; + + LOG_ARG("bufferLen: %u", bufferLen); + LOG_URI(uriP); + + buffer[0] = '/'; + + if (uriP == NULL) + { + if (depthP) *depthP = URI_DEPTH_OBJECT; + return 1; + } + + head = 1; + + res = utils_intToText(uriP->objectId, buffer + head, bufferLen - head); + if (res <= 0) return -1; + head += res; + if (head >= bufferLen - 1) return -1; + if (depthP) *depthP = URI_DEPTH_OBJECT_INSTANCE; + + if (LWM2M_URI_IS_SET_INSTANCE(uriP)) + { + buffer[head] = '/'; + head++; + res = utils_intToText(uriP->instanceId, buffer + head, bufferLen - head); + if (res <= 0) return -1; + head += res; + if (head >= bufferLen - 1) return -1; + if (depthP) *depthP = URI_DEPTH_RESOURCE; + if (LWM2M_URI_IS_SET_RESOURCE(uriP)) + { + buffer[head] = '/'; + head++; + res = utils_intToText(uriP->resourceId, buffer + head, bufferLen - head); + if (res <= 0) return -1; + head += res; + if (head >= bufferLen - 1) return -1; + if (depthP) *depthP = URI_DEPTH_RESOURCE_INSTANCE; + } + } + + buffer[head] = '/'; + head++; + + LOG_ARG("length: %u, buffer: \"%.*s\"", head, head, buffer); + + return head; +}