avalluri / open-tr069

Automatically exported from code.google.com/p/open-tr069
7 stars 3 forks source link

Problem parsing TR135 path #5

Open GoogleCodeExporter opened 9 years ago

GoogleCodeExporter commented 9 years ago
First of all: thank you for the good project. It's seems promising even if it 
lacks for now many features as SSL, download and upload.

I'm trying to use the data model on TR135 paths and I've run into a parse error.
I was trying to access the following parameter:

Device.Services.STBService.1.Components.FrontEndNumberOfEntries

Where
Device: object
Services: object
STBService: multi-object
Components: object
FrontEndNumberOfEntries: a unsigned integer

The function evcpe_repo_locate() cannot parse this path and exit with an error: 
"failed to convert to integer: Components"

I've make a little path that resolved my problem and I hope this is correct. 
The data model design seems to be good but it lack documentation (doxygen as an 
example):

int evcpe_repo_locate(struct evcpe_repo *repo, const char *name,
        struct evcpe_obj **obj, struct evcpe_attr **attr, unsigned int *index)
{
    int rc;
    const char *start, *end;
    int inst_read = 0; /* Set when an instance is read */

    *obj = repo->root;
    *attr = NULL;
    start = end = name;
    while(*end != '\0') {
        if (*end != '.') {
            end ++;
            continue;
        }
        if (end == start) {
            // expression neglecting root object (compatible to all
            // TR-069 enabled device
            *attr = RB_ROOT(&repo->root->attrs);
            *obj = (*attr)->value.object;
        } else if ((*attr) && (*attr)->schema->type == EVCPE_TYPE_MULTIPLE) {
            if (!inst_read) {
                if (!(*index = atoi(start)) && errno) {
                    evcpe_error(__func__, "failed to convert to integer: "
                            "%.*s", end - start, start);
                    rc = EINVAL;
                    goto finally;
                }
                if (*index <= 0) {
                    evcpe_error(__func__, "invalid instance number: "
                            "%d", *index);
                    rc = EINVAL;
                    goto finally;
                }
                if ((rc = evcpe_attr_idx_obj(*attr, (*index) - 1, obj))) {
                    evcpe_error(__func__, "indexed object doesn't exist: "
                            "[%d]", (*index) - 1);
                    goto finally;
                }
            } else {
                /* Read the next object */
                if ((rc = evcpe_obj_get(*obj, start, end - start, attr))) {
                    evcpe_error(__func__, "failed to get attribute: %.*s",
                            end - start, start);
                    goto finally;
                }
                if ((rc = evcpe_attr_get_obj(*attr, obj))) {
                    evcpe_error(__func__, "failed to get object: %.*s",
                            end - start, start);
                    goto finally;
                }
            }
        } else if ((rc = evcpe_obj_get(*obj, start, end - start, attr))) {
            evcpe_error(__func__, "failed to get attribute: %.*s",
                    end - start, start);
            goto finally;
//      } else if (!(*attr)) {
//          evcpe_error(__func__, "attribute doesn't exist: %.*s",
//                  end - start, start);
//          rc = EINVAL;
//          goto finally;
        } else if ((*attr)->schema->type == EVCPE_TYPE_MULTIPLE) {
            inst_read = 0;
        } else if ((*attr)->schema->type == EVCPE_TYPE_OBJECT) {
            *obj = (*attr)->value.object;
        } else {
            evcpe_error(__func__, "not an object/multiple attribute: %s",
                    (*attr)->schema->name);
            rc = EVCPE_CPE_INVALID_PARAM_NAME;
            goto finally;
        }
        start = ++ end;
    }
    if (start != end) {
        if ((rc = evcpe_obj_get(*obj, start, end - start, attr))) {
            evcpe_error(__func__, "failed to get attribute: %.*s",
                    end - start, start);
            goto finally;
        } else if ((*attr)->schema->type == EVCPE_TYPE_OBJECT ||
                (*attr)->schema->type == EVCPE_TYPE_MULTIPLE) {
            evcpe_error(__func__, "not a simple attribute: %.*s",
                    end - start, start);
            rc = EVCPE_CPE_INVALID_PARAM_NAME;
            goto finally;
        }
    }
    rc = 0;

finally:
    return rc;
}

I've added a boolean state to bypass reading the instance number {i} when 
applicable.

Again many thanks for the program and your effort.

Original issue reported on code.google.com by atef.hal...@gmail.com on 15 Aug 2011 at 7:07

GoogleCodeExporter commented 9 years ago
Well, even the above patch does not work in all cases. I've tried the following 
path and it fails miserably: 
"Device.Services.STBService.{i}.Components.FrontEnd.{i}.DVBT.ServiceListDatabase
.LogicalChannel.{i}.LogicalChannelNumber".
It will fail also for a more complex path 
"Device.Services.STBService.{i}.Components.FrontEnd.{i}.DVBT.ServiceListDatabase
.LogicalChannel.{i}.Service.{i}.Name"

I've made a new more generic pâtch that fit my needs. however, I'm still 
looking for a more generic way to deal with instances searching.

[CODE]
int evcpe_repo_locate(struct evcpe_repo *repo, const char *name,
        struct evcpe_obj **obj, struct evcpe_attr **attr, unsigned int *index)
{
    int rc;
    const char *start, *end;

    *obj = repo->root;
    *attr = NULL;
    start = end = name;

    while(*end != '\0') {
        if (*end != '.') {
            end ++;
            continue;
        }
        if (end == start) {
            // expression neglecting root object (compatible to all
            // TR-069 enabled device
            *attr = RB_ROOT(&repo->root->attrs);
            *obj = (*attr)->value.object;
        } else if ((*attr) && (*attr)->schema->type == EVCPE_TYPE_MULTIPLE) {
            if (!(*index = atoi(start)) && errno) {
                evcpe_error(__func__, "failed to convert to integer: "
                        "%.*s", end - start, start);
                rc = ENOMEM;
                goto finally;
            }
            if (*index <= 0) {
                evcpe_error(__func__, "invalid instance number: "
                        "%d", *index);
                rc = ENOMEM;
                goto finally;
            }
            if ((rc = evcpe_attr_idx_obj(*attr, (*index) - 1, obj))) {
                evcpe_error(__func__, "indexed object doesn't exist: "
                        "[%d]", (*index) - 1);
                goto finally;
            }

      /* Skip the {i} instance reference */
      end = start;
      while ((*end != '\0') && (*end != '.')) {
        ++end;
      }
      /* Look for the next child attribute */
      start = ++end;
      while ((*end != '\0') && (*end != '.')) {
        ++end;
      }
      if ((end - start) > 1) {
        if (!(*attr = evcpe_obj_find(*obj, start, (unsigned int)(end - start)))) {
          evcpe_error(__func__, "child attribute does not exists: %.*s",
               (end - start), start);
          goto finally;
        }
        if (EVCPE_TYPE_OBJECT == (*attr)->schema->type) {
          if ((rc = evcpe_attr_get_obj(*attr, obj))) {
            evcpe_error(__func__, "failed to get object: %.*s",
                 (end - start), start);
            goto finally;
          }
        }
        else {
          *obj = NULL;
          *obj_index = 0;
        }
      }
      if ('\0' == *end) {
        /* The end of parameter's name has been reached */
        start = end; /* Simulate a stop condition */
        break;
      }         
        } else if ((rc = evcpe_obj_get(*obj, start, end - start, attr))) {
            evcpe_error(__func__, "failed to get attribute: %.*s",
                    end - start, start);
            goto finally;
//      } else if (!(*attr)) {
//          evcpe_error(__func__, "attribute doesn't exist: %.*s",
//                  end - start, start);
//          rc = EINVAL;
//          goto finally;
        } else if ((*attr)->schema->type == EVCPE_TYPE_MULTIPLE) {
        } else if ((*attr)->schema->type == EVCPE_TYPE_OBJECT) {
            *obj = (*attr)->value.object;
        } else {
            evcpe_error(__func__, "not an object/multiple attribute: %s",
                    (*attr)->schema->name);
            rc = EVCPE_CPE_INVALID_PARAM_NAME;
            goto finally;
        }
        start = ++ end;
    }
    if (start != end) {
        if ((rc = evcpe_obj_get(*obj, start, end - start, attr))) {
            evcpe_error(__func__, "failed to get attribute: %.*s",
                    end - start, start);
            goto finally;
        } else if ((*attr)->schema->type == EVCPE_TYPE_OBJECT ||
                (*attr)->schema->type == EVCPE_TYPE_MULTIPLE) {
            evcpe_error(__func__, "not a simple attribute: %.*s",
                    end - start, start);
            rc = EVCPE_CPE_INVALID_PARAM_NAME;
            goto finally;
        }
    }
    rc = 0;

finally:
    return rc;
}
[/CODE]

Original comment by atef.hal...@gmail.com on 22 Sep 2011 at 8:17