Exemple #1
0
static void
parseMethodResponseElt(xmlrpc_env *        const envP,
                       const xml_element * const methodResponseEltP,
                       xmlrpc_value **     const resultPP,
                       int *               const faultCodeP,
                       const char **       const faultStringP) {
    
    XMLRPC_ASSERT(xmlrpc_streq(xml_element_name(methodResponseEltP),
                               "methodResponse"));

    if (xml_element_children_size(methodResponseEltP) == 1) {
        xml_element * const child =
            xml_element_children(methodResponseEltP)[0];
        
        if (xmlrpc_streq(xml_element_name(child), "params")) {
            /* It's a successful response */
            parseParamsElement(envP, child, resultPP);
            *faultStringP = NULL;
        } else if (xmlrpc_streq(xml_element_name(child), "fault")) {
            /* It's a failure response */
            parseFaultElement(envP, child, faultCodeP, faultStringP);
        } else
            setParseFault(envP,
                          "<methodResponse> must contain <params> or <fault>, "
                          "but contains <%s>.", xml_element_name(child));
    } else
        setParseFault(envP,
                      "<methodResponse> has %u children, should have 1.",
                      xml_element_children_size(methodResponseEltP));
}
static xmlrpc_value *
convert_params(xmlrpc_env *        const envP,
               const xml_element * const elemP) {
/*----------------------------------------------------------------------------
   Convert an XML element representing a list of parameters (i.e.  a
   <params> element) to an xmlrpc_value of type array.  Note that an
   array is normally represented in XML by a <value> element.  We use
   type xmlrpc_value to represent the parameter list just for convenience.
-----------------------------------------------------------------------------*/
    xmlrpc_value *array, *item;
    int size, i;
    xml_element **params, *param, *value;

    XMLRPC_ASSERT_ENV_OK(envP);
    XMLRPC_ASSERT(elemP != NULL);

    /* Set up our error-handling preconditions. */
    array = item = NULL;

    /* Allocate an array to hold our parameters. */
    array = xmlrpc_build_value(envP, "()");
    XMLRPC_FAIL_IF_FAULT(envP);

    /* We're responsible for checking our own element name. */
    CHECK_NAME(envP, elemP, "params");    

    /* Iterate over our children. */
    size = xml_element_children_size(elemP);
    params = xml_element_children(elemP);
    for (i = 0; i < size; ++i) {
        unsigned int const maxNest = xmlrpc_limit_get(XMLRPC_NESTING_LIMIT_ID);

        param = params[i];
        CHECK_NAME(envP, param, "param");
        CHECK_CHILD_COUNT(envP, param, 1);

        value = xml_element_children(param)[0];

        CHECK_NAME(envP, value, "value");

        xmlrpc_parseValue(envP, maxNest, value, &item);
        XMLRPC_FAIL_IF_FAULT(envP);

        xmlrpc_array_append_item(envP, array, item);
        xmlrpc_DECREF(item);
        item = NULL;
        XMLRPC_FAIL_IF_FAULT(envP);
    }

 cleanup:
    if (envP->fault_occurred) {
        if (array)
            xmlrpc_DECREF(array);
        if (item)
            xmlrpc_DECREF(item);
        return NULL;
    }
    return array;
}
static void
parseArray(xmlrpc_env *    const envP,
           unsigned int    const maxRecursion,
           xml_element *   const arrayElemP,
           xmlrpc_value ** const arrayPP) {

    xmlrpc_value * arrayP;

    XMLRPC_ASSERT_ENV_OK(envP);
    XMLRPC_ASSERT(arrayElemP != NULL);

    arrayP = xmlrpc_array_new(envP);
    if (!envP->fault_occurred) {
        unsigned int const childCount = xml_element_children_size(arrayElemP);

        if (childCount != 1)
            setParseFault(envP,
                          "<array> element has %u children.  Only one <data> "
                          "makes sense.", childCount);
        else {
            xml_element * const dataElemP =
                xml_element_children(arrayElemP)[0];
            const char * const elemName = xml_element_name(dataElemP);

            if (!xmlrpc_streq(elemName, "data"))
                setParseFault(envP,
                              "<array> element has <%s> child.  Only <data> "
                              "makes sense.", elemName);
            else {
                xml_element ** const values = xml_element_children(dataElemP);
                unsigned int const size = xml_element_children_size(dataElemP);

                unsigned int i;

                for (i = 0; i < size && !envP->fault_occurred; ++i)
                    parseArrayDataChild(envP, values[i], maxRecursion, arrayP);
            }
        }
        if (envP->fault_occurred)
            xmlrpc_DECREF(arrayP);
        else
            *arrayPP = arrayP;
    }
}
static void test_expat (void)
{
    xmlrpc_env env;
    xml_element *elem, *array, *data, *value1, *i4;
    char *cdata;
    size_t size;

    xmlrpc_env_init(&env);

    /* Parse a moderately complex XML document. */
    xml_parse(&env, expat_data, strlen(expat_data), &elem);
    TEST_NO_FAULT(&env);
    TEST(elem != NULL);

    /* Verify our results. */
    TEST(streq(xml_element_name(elem), "value"));
    TEST(xml_element_children_size(elem) == 1);
    array = xml_element_children(elem)[0];
    TEST(streq(xml_element_name(array), "array"));
    TEST(xml_element_children_size(array) == 1);
    data = xml_element_children(array)[0];
    TEST(streq(xml_element_name(data), "data"));
    TEST(xml_element_children_size(data) > 1);
    value1 = xml_element_children(data)[0];
    TEST(streq(xml_element_name(value1), "value"));
    TEST(xml_element_children_size(value1) == 1);
    i4 = xml_element_children(value1)[0];
    TEST(streq(xml_element_name(i4), "i4"));
    TEST(xml_element_children_size(i4) == 0);
    cdata = xml_element_cdata(i4);
    size = xml_element_cdata_size(i4);
    TEST(size == strlen("2147483647"));
    TEST(memcmp(cdata, "2147483647", strlen("2147483647")) == 0);

    /* Test cleanup code (w/memprof). */
    xml_element_free(elem);

    /* Test broken XML */
    xml_parse(&env, expat_error_data, strlen(expat_error_data), &elem);
    TEST(env.fault_occurred);

    xmlrpc_env_clean(&env);
}
Exemple #5
0
static void
describeXmlElement(const xml_element * const elemP,
                   const char *        const prefix) {

    unsigned int i;

    printf("%sXML element type:         '%s'\n",
           prefix, xml_element_name(elemP));

    printf("%sNumber of child elements: %u\n",
           prefix, xml_element_children_size(elemP));

    for (i = 0; i < xml_element_children_size(elemP); ++i) {
        char * const newPrefix = malloc(strlen(prefix) + 2);
        sprintf(newPrefix, "%s  ", prefix);
        describeXmlElement(xml_element_children(elemP)[i], newPrefix);
        free(newPrefix);
    }
}
Exemple #6
0
static void
parseCallChildren(xmlrpc_env *    const envP,
                  xml_element *   const callElemP,
                  const char **   const methodNameP,
                  xmlrpc_value ** const paramArrayPP ) {
/*----------------------------------------------------------------------------
  Parse the children of a <methodCall> XML element *callElemP.  They should
  be <methodName> and <params>.
-----------------------------------------------------------------------------*/
    size_t const callChildCount = xml_element_children_size(callElemP);

    xml_element * nameElemP;
        
    XMLRPC_ASSERT(xmlrpc_streq(xml_element_name(callElemP), "methodCall"));
    
    nameElemP = getChildByName(envP, callElemP, "methodName");
    
    if (!envP->fault_occurred) {
        parseMethodNameElement(envP, nameElemP, methodNameP);
            
        if (!envP->fault_occurred) {
            /* Convert our parameters. */
            if (callChildCount > 1) {
                xml_element * paramsElemP;

                paramsElemP = getChildByName(envP, callElemP, "params");
                    
                if (!envP->fault_occurred)
                    *paramArrayPP = convertParams(envP, paramsElemP);
            } else {
                /* Workaround for Ruby XML-RPC and old versions of
                   xmlrpc-epi.  Future improvement: Instead of looking
                   at child count, we should just check for existence
                   of <params>.
                */
                *paramArrayPP = xmlrpc_array_new(envP);
            }
            if (!envP->fault_occurred) {
                if (callChildCount > 2)
                    setParseFault(envP, "<methodCall> has extraneous "
                                  "children, other than <methodName> and "
                                  "<params>.  Total child count = %u",
                                  callChildCount);
                    
                if (envP->fault_occurred)
                    xmlrpc_DECREF(*paramArrayPP);
            }
            if (envP->fault_occurred)
                xmlrpc_strfree(*methodNameP);
        }
    }
}
Exemple #7
0
static void
parseFaultElement(xmlrpc_env *        const envP,
                  const xml_element * const faultElement,
                  int *               const faultCodeP,
                  const char **       const faultStringP) {
                  
    unsigned int const maxRecursion = (unsigned int)
        xmlrpc_limit_get(XMLRPC_NESTING_LIMIT_ID);

    XMLRPC_ASSERT(xmlrpc_streq(xml_element_name(faultElement), "fault"));

    if (xml_element_children_size(faultElement) != 1)
        setParseFault(envP, "<fault> element should have 1 child, "
                      "but it has %u.",
                      xml_element_children_size(faultElement));
    else {
        xml_element * const faultValueP =
            xml_element_children(faultElement)[0];
        const char * const elemName = xml_element_name(faultValueP);

        if (!xmlrpc_streq(elemName, "value"))
            setParseFault(envP,
                          "<fault> contains a <%s> element.  "
                          "Only <value> makes sense.",
                          elemName);
        else {
            xmlrpc_value * faultVP;

            xmlrpc_parseValue(envP, maxRecursion, faultValueP, &faultVP);
        
            if (!envP->fault_occurred) {
                interpretFaultValue(envP, faultVP, faultCodeP, faultStringP);
                
                xmlrpc_DECREF(faultVP);
            }
        }
    }
}
Exemple #8
0
static void
parseMethodNameElement(xmlrpc_env *  const envP,
                       xml_element * const nameElemP,
                       const char ** const methodNameP) {
    
    XMLRPC_ASSERT(xmlrpc_streq(xml_element_name(nameElemP), "methodName"));

    if (xml_element_children_size(nameElemP) > 0)
        setParseFault(envP, "A <methodName> element should not have "
                      "children.  This one has %u of them.",
                      xml_element_children_size(nameElemP));
    else {
        const char * const cdata = xml_element_cdata(nameElemP);

        xmlrpc_validate_utf8(envP, cdata, strlen(cdata));

        if (!envP->fault_occurred) {
            *methodNameP = strdup(cdata);
            if (*methodNameP == NULL)
                xmlrpc_faultf(envP,
                              "Could not allocate memory for method name");
        }
    }
}            
static void
parseStruct(xmlrpc_env *    const envP,
            unsigned int    const maxRecursion,
            xml_element *   const elemP,
            xmlrpc_value ** const structPP) {
/*----------------------------------------------------------------------------
   Parse the <struct> element 'elemP'.
-----------------------------------------------------------------------------*/
    xmlrpc_value * structP;

    XMLRPC_ASSERT_ENV_OK(envP);
    XMLRPC_ASSERT(elemP != NULL);

    structP = xmlrpc_struct_new(envP);
    if (!envP->fault_occurred) {
        /* Iterate over our children, extracting key/value pairs. */

        xml_element ** const members = xml_element_children(elemP);
        unsigned int const size = xml_element_children_size(elemP);

        unsigned int i;

        for (i = 0; i < size && !envP->fault_occurred; ++i) {
            const char * const elemName = xml_element_name(members[i]);

            if (!xmlrpc_streq(elemName, "member"))
                setParseFault(envP, "<%s> element found where only <member> "
                              "makes sense", elemName);
            else {
                xmlrpc_value * keyP;
                xmlrpc_value * valueP;

                parseMember(envP, members[i], maxRecursion, &keyP, &valueP);

                if (!envP->fault_occurred) {
                    xmlrpc_struct_set_value_v(envP, structP, keyP, valueP);

                    xmlrpc_DECREF(keyP);
                    xmlrpc_DECREF(valueP);
                }
            }
        }
        if (envP->fault_occurred)
            xmlrpc_DECREF(structP);
        else
            *structPP = structP;
    }
}
static void
parseName(xmlrpc_env *    const envP,
          xml_element *   const nameElemP,
          xmlrpc_value ** const valuePP) {

    unsigned int const childCount = xml_element_children_size(nameElemP);

    if (childCount > 0)
        setParseFault(envP, "<name> element has %u children.  "
                      "Should have none.", childCount);
    else {
        const char * const cdata     = xml_element_cdata(nameElemP);
        size_t       const cdataSize = xml_element_cdata_size(nameElemP);

        *valuePP = xmlrpc_string_new_lp(envP, cdataSize, cdata);
    }
}
static xml_element *
get_child_by_name (xmlrpc_env *env, xml_element *parent, char *name)
{
    size_t child_count, i;
    xml_element **children;

    children = xml_element_children(parent);
    child_count = xml_element_children_size(parent);
    for (i = 0; i < child_count; i++) {
        if (xmlrpc_streq(xml_element_name(children[i]), name))
            return children[i];
    }
    
    xmlrpc_env_set_fault_formatted(env, XMLRPC_PARSE_ERROR,
                                   "Expected <%s> to have child <%s>",
                                   xml_element_name(parent), name);
    return NULL;
}
Exemple #12
0
static xml_element *
getChildByName (xmlrpc_env *  const envP,
                xml_element * const parentP,
                const char *  const name) {

    size_t const childCount = xml_element_children_size(parentP);
    xml_element ** const childrenP = xml_element_children(parentP);

    unsigned int i;

    for (i = 0; i < childCount; ++i) {
        if (xmlrpc_streq(xml_element_name(childrenP[i]), name))
            return childrenP[i];
    }
    
    setParseFault(envP, "Expected <%s> to have child <%s>",
                  xml_element_name(parentP), name);
    return NULL;
}
static void
getValueChild(xmlrpc_env *    const envP,
              xml_element *   const parentP,
              xml_element * * const childPP) {

    xml_element ** const children   = xml_element_children(parentP);
    size_t         const childCount = xml_element_children_size(parentP);

    xml_element * childP;
    unsigned int i;

    for (i = 0, childP = NULL; i < childCount && !childP; ++i) {
        if (xmlrpc_streq(xml_element_name(children[i]), "value"))
            childP = children[i];
    }
    if (!childP)
        xmlrpc_env_set_fault(envP, XMLRPC_PARSE_ERROR,
                             "<member> has no <value> child");
    else
        *childPP = childP;
}
static void
parseMember(xmlrpc_env *    const envP,
            xml_element *   const memberP,
            unsigned int    const maxRecursion,
            xmlrpc_value ** const keyPP,
            xmlrpc_value ** const valuePP) {

    unsigned int const childCount = xml_element_children_size(memberP);

    if (childCount != 2)
        setParseFault(envP,
                      "<member> element has %u children.  Only one <name> and "
                      "one <value> make sense.", childCount);
    else {
        xml_element * nameElemP;

        getNameChild(envP, memberP, &nameElemP);

        if (!envP->fault_occurred) {
            parseName(envP, nameElemP, keyPP);

            if (!envP->fault_occurred) {
                xml_element * valueElemP;

                getValueChild(envP, memberP, &valueElemP);
                
                if (!envP->fault_occurred)
                    xmlrpc_parseValue(envP, maxRecursion-1, valueElemP,
                                      valuePP);

                if (envP->fault_occurred)
                    xmlrpc_DECREF(*keyPP);
            }
        }
    }
}