Back to index

php5  5.3.10
Functions
xmlrpc_introspection.c File Reference
#include "queue.h"
#include "xmlrpc.h"
#include "xmlrpc_private.h"
#include "xmlrpc_introspection_private.h"
#include <string.h>
#include <stdlib.h>
#include <stdarg.h>

Go to the source code of this file.

Functions

static XMLRPC_VALUE xi_system_describe_methods_cb (XMLRPC_SERVER server, XMLRPC_REQUEST input, void *userData)
static XMLRPC_VALUE xi_system_list_methods_cb (XMLRPC_SERVER server, XMLRPC_REQUEST input, void *userData)
static XMLRPC_VALUE xi_system_method_signature_cb (XMLRPC_SERVER server, XMLRPC_REQUEST input, void *userData)
static XMLRPC_VALUE xi_system_method_help_cb (XMLRPC_SERVER server, XMLRPC_REQUEST input, void *userData)
static XMLRPC_VALUE find_named_value (XMLRPC_VALUE list, const char *needle)
static void check_docs_loaded (XMLRPC_SERVER server, void *userData)
static void describe_method (XMLRPC_SERVER server, XMLRPC_VALUE vector, const char *method)
void xi_register_system_methods (XMLRPC_SERVER server)
static XMLRPC_VALUE describeValue_worker (const char *type, const char *id, const char *desc, int optional, const char *default_val, XMLRPC_VALUE sub_params)
XMLRPC_VALUE xml_element_to_method_description (xml_element *el, XMLRPC_ERROR err)
XMLRPC_VALUE XMLRPC_IntrospectionCreateDescription (const char *xml, XMLRPC_ERROR err)
int XMLRPC_ServerAddIntrospectionData (XMLRPC_SERVER server, XMLRPC_VALUE desc)
int XMLRPC_ServerRegisterIntrospectionCallback (XMLRPC_SERVER server, XMLRPC_IntrospectionCallback cb)

Function Documentation

static void check_docs_loaded ( XMLRPC_SERVER  server,
void *  userData 
) [static]

Definition at line 94 of file xmlrpc_introspection.c.

                                                                    {
   if(server) {
      q_iter qi = Q_Iter_Head_F(&server->docslist);
      while( qi ) {
         doc_method* dm = Q_Iter_Get_F(qi);
         if(dm && !dm->b_called) {
            dm->method(server, userData);
            dm->b_called = 1;
         }
         qi = Q_Iter_Next_F(qi);
      }
   }
}

Here is the caller graph for this function:

static void describe_method ( XMLRPC_SERVER  server,
XMLRPC_VALUE  vector,
const char *  method 
) [inline, static]

Definition at line 110 of file xmlrpc_introspection.c.

                                                                                                  {
   if(method) {
      server_method* sm = find_method(server, method);
      if(sm) {
         XMLRPC_AddValueToVector(vector, sm->desc);
      }
   }
}

Here is the call graph for this function:

Here is the caller graph for this function:

static XMLRPC_VALUE describeValue_worker ( const char *  type,
const char *  id,
const char *  desc,
int  optional,
const char *  default_val,
XMLRPC_VALUE  sub_params 
) [static]

Definition at line 287 of file xmlrpc_introspection.c.

                                                                                                                                                             {
   XMLRPC_VALUE xParam = NULL;
   if(id || desc) {
      xParam = XMLRPC_CreateVector(NULL, xmlrpc_vector_struct);
      XMLRPC_VectorAppendString(xParam, xi_token_name, id, 0);
      XMLRPC_VectorAppendString(xParam, xi_token_type, type, 0);
      XMLRPC_VectorAppendString(xParam, xi_token_description, desc, 0);
      if(optional != 2) {
         XMLRPC_VectorAppendInt(xParam, xi_token_optional, optional);
      }
      if(optional == 1 && default_val) {
         XMLRPC_VectorAppendString(xParam, xi_token_default, default_val, 0);
      }
      XMLRPC_AddValueToVector(xParam, sub_params);
   }
   return xParam;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static XMLRPC_VALUE find_named_value ( XMLRPC_VALUE  list,
const char *  needle 
) [inline, static]

Definition at line 80 of file xmlrpc_introspection.c.

                                                                                   {
   XMLRPC_VALUE xIter = XMLRPC_VectorRewind(list);
   while(xIter) {
      const char* name = XMLRPC_VectorGetStringWithID(xIter, xi_token_name);
      if(name && !strcmp(name, needle)) {
         return xIter;
      }
      xIter = XMLRPC_VectorNext(list);
   }
   return NULL;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static XMLRPC_VALUE xi_system_describe_methods_cb ( XMLRPC_SERVER  server,
XMLRPC_REQUEST  input,
void *  userData 
) [static]

Definition at line 122 of file xmlrpc_introspection.c.

                                                                                                              {
   XMLRPC_VALUE xParams = XMLRPC_VectorRewind(XMLRPC_RequestGetData(input));
   XMLRPC_VALUE xResponse = XMLRPC_CreateVector(NULL, xmlrpc_vector_struct);
   XMLRPC_VALUE xMethodList = XMLRPC_CreateVector("methodList", xmlrpc_vector_array);
   XMLRPC_VALUE xTypeList = NULL;
   int bAll = 1;

   /* lazy loading of introspection data */
   check_docs_loaded(server, userData);

   xTypeList = XMLRPC_VectorGetValueWithID(server->xIntrospection, "typeList");

   XMLRPC_AddValueToVector(xResponse, xTypeList);
   XMLRPC_AddValueToVector(xResponse, xMethodList);

   /* check if we have any param */
   if(xParams) {
      /* check if string or vector (1 or n) */
      XMLRPC_VALUE_TYPE type = XMLRPC_GetValueType(xParams);
      if(type == xmlrpc_string) {
         /* just one.  spit it out. */
         describe_method(server, xMethodList, XMLRPC_GetValueString(xParams));
         bAll = 0;
      }
      else if(type == xmlrpc_vector) {
         /* multiple.  spit all out */
         XMLRPC_VALUE xIter = XMLRPC_VectorRewind(xParams);
         while(xIter) {
            describe_method(server, xMethodList, XMLRPC_GetValueString(xIter));
            xIter = XMLRPC_VectorNext(xParams);
         }
         bAll = 0;
      }
   }

   /* otherwise, default to sending all methods */
   if(bAll) {
      q_iter qi = Q_Iter_Head_F(&server->methodlist);
      while( qi ) {
         server_method* sm = Q_Iter_Get_F(qi);
         if(sm) {
            XMLRPC_AddValueToVector(xMethodList, sm->desc);
         }
         qi = Q_Iter_Next_F(qi);
      }
   }
   
   return xResponse;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static XMLRPC_VALUE xi_system_list_methods_cb ( XMLRPC_SERVER  server,
XMLRPC_REQUEST  input,
void *  userData 
) [static]

Definition at line 173 of file xmlrpc_introspection.c.

                                                                                                          {
   XMLRPC_VALUE xResponse = XMLRPC_CreateVector(NULL, xmlrpc_vector_array);

   q_iter qi = Q_Iter_Head_F(&server->methodlist);
   while( qi ) {
      server_method* sm = Q_Iter_Get_F(qi);
      if(sm) {
         XMLRPC_VectorAppendString(xResponse, 0, sm->name, 0);
      }
      qi = Q_Iter_Next_F(qi);
   }
   return xResponse;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static XMLRPC_VALUE xi_system_method_help_cb ( XMLRPC_SERVER  server,
XMLRPC_REQUEST  input,
void *  userData 
) [static]

Definition at line 249 of file xmlrpc_introspection.c.

                                                                                                         {
   const char* method = XMLRPC_GetValueString(XMLRPC_VectorRewind(XMLRPC_RequestGetData(input)));
   XMLRPC_VALUE xResponse = NULL;

   /* lazy loading of introspection data */
   check_docs_loaded(server, userData);

   if(method) {
      server_method* sm = find_method(server, method);
      if(sm && sm->desc) {
         const char* help = XMLRPC_VectorGetStringWithID(sm->desc, xi_token_purpose);

         /* returns a documentation string, or empty string */
         xResponse = XMLRPC_CreateValueString(NULL, help ? help : xi_token_empty, 0);
      }
   }

   return xResponse;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static XMLRPC_VALUE xi_system_method_signature_cb ( XMLRPC_SERVER  server,
XMLRPC_REQUEST  input,
void *  userData 
) [static]

Definition at line 190 of file xmlrpc_introspection.c.

                                                                                                              {
   const char* method = XMLRPC_GetValueString(XMLRPC_VectorRewind(XMLRPC_RequestGetData(input)));
   XMLRPC_VALUE xResponse = NULL;

   /* lazy loading of introspection data */
   check_docs_loaded(server, userData);

   if(method) {
      server_method* sm = find_method(server, method);
      if(sm && sm->desc) {
         XMLRPC_VALUE xTypesArray = XMLRPC_CreateVector(NULL, xmlrpc_vector_array);
         XMLRPC_VALUE xIter, xParams, xSig, xSigIter;
         const char* type;

         /* array of possible signatures.  */
         xResponse = XMLRPC_CreateVector(NULL, xmlrpc_vector_array);

         /* find first signature */
         xSig = XMLRPC_VectorGetValueWithID(sm->desc, xi_token_signatures);
         xSigIter = XMLRPC_VectorRewind( xSig );

         /* iterate through sigs */
         while(xSigIter) {
            /* first type is the return value */
            type = XMLRPC_VectorGetStringWithID(XMLRPC_VectorRewind(
                                                 XMLRPC_VectorGetValueWithID(xSigIter, xi_token_returns)), 
                                                xi_token_type);
            XMLRPC_AddValueToVector(xTypesArray, 
                                    XMLRPC_CreateValueString(NULL, 
                                                             type ? type : type_to_str(xmlrpc_none, 0), 
                                    0));

            /* the rest are parameters */
            xParams = XMLRPC_VectorGetValueWithID(xSigIter, xi_token_params);
            xIter = XMLRPC_VectorRewind(xParams);

            /* iter through params, adding to types array */
            while(xIter) {
               XMLRPC_AddValueToVector(xTypesArray,
                                       XMLRPC_CreateValueString(NULL, 
                                                                XMLRPC_VectorGetStringWithID(xIter, xi_token_type),
                                                                0));
               xIter = XMLRPC_VectorNext(xParams);
            }

            /* add types for this signature */
            XMLRPC_AddValueToVector(xResponse, xTypesArray);

            xSigIter = XMLRPC_VectorNext( xSig );
         }
      }
   }

   return xResponse;
}

Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 309 of file xmlrpc_introspection.c.

                                                                                  {
   XMLRPC_VALUE xReturn = NULL;

   if(el->name) {
      const char* name = NULL;
      const char* type = NULL;
      const char* basetype = NULL;
      const char* desc = NULL;
      const char* def = NULL;
      int optional = 0;
      xml_element_attr* attr_iter = Q_Head(&el->attrs);

      /* grab element attributes up front to save redundant while loops */
      while(attr_iter) {
         if(!strcmp(attr_iter->key, "name")) {
            name = attr_iter->val;
         }
         else if(!strcmp(attr_iter->key, "type")) {
            type = attr_iter->val;
         }
         else if(!strcmp(attr_iter->key, "basetype")) {
            basetype = attr_iter->val;
         }
         else if(!strcmp(attr_iter->key, "desc")) {
            desc = attr_iter->val;
         }
         else if(!strcmp(attr_iter->key, "optional")) {
            if(attr_iter->val && !strcmp(attr_iter->val, "yes")) {
               optional = 1;
            }
         }
         else if(!strcmp(attr_iter->key, "default")) {
            def = attr_iter->val;
         }
         attr_iter = Q_Next(&el->attrs);
      }

      /* value and typeDescription behave about the same */
      if(!strcmp(el->name, "value") || !strcmp(el->name, "typeDescription")) {
         XMLRPC_VALUE xSubList = NULL;
         const char* ptype = !strcmp(el->name, "value") ? type : basetype;
         if(ptype) {
            if(Q_Size(&el->children) &&
               (!strcmp(ptype, "array") || !strcmp(ptype, "struct") || !strcmp(ptype, "mixed"))) {
               xSubList = XMLRPC_CreateVector("member", xmlrpc_vector_array);

               if(xSubList) {
                  xml_element* elem_iter = Q_Head(&el->children);
                  while(elem_iter) {
                     XMLRPC_AddValueToVector(xSubList, 
                                             xml_element_to_method_description(elem_iter, err));
                     elem_iter = Q_Next(&el->children);
                  }
               }
            }
            xReturn = describeValue_worker(ptype, name, (desc ? desc : (xSubList ? NULL : el->text.str)), optional, def, xSubList);
         }
      }

      /* these three kids are about equivalent */
      else if(!strcmp(el->name, "params") || 
              !strcmp(el->name, "returns") || 
              !strcmp(el->name, "signature")) {
         if(Q_Size(&el->children)) {
            xml_element* elem_iter = Q_Head(&el->children);
            xReturn = XMLRPC_CreateVector(!strcmp(el->name, "signature") ? NULL : el->name, xmlrpc_vector_struct);


            while(elem_iter) {
               XMLRPC_AddValueToVector(xReturn, 
                                       xml_element_to_method_description(elem_iter, err));
               elem_iter = Q_Next(&el->children);
            }
         }
      }


      else if(!strcmp(el->name, "methodDescription")) {
         xml_element* elem_iter = Q_Head(&el->children);
         xReturn = XMLRPC_CreateVector(NULL, xmlrpc_vector_struct);

         XMLRPC_VectorAppendString(xReturn, xi_token_name, name, 0);

         while(elem_iter) {
            XMLRPC_AddValueToVector(xReturn, 
                                    xml_element_to_method_description(elem_iter, err));
            elem_iter = Q_Next(&el->children);
         }
      }

      /* items are slightly special */
      else if(!strcmp(el->name, "item")) {
         xReturn = XMLRPC_CreateValueString(name, el->text.str, el->text.len);
      }

      /* sure.  we'll let any ol element with children through */
      else if(Q_Size(&el->children)) {
         xml_element* elem_iter = Q_Head(&el->children);
         xReturn = XMLRPC_CreateVector(el->name, xmlrpc_vector_mixed);

         while(elem_iter) {
            XMLRPC_AddValueToVector(xReturn, 
                                    xml_element_to_method_description(elem_iter, err));
            elem_iter = Q_Next(&el->children);
         }
      }

      /* or anything at all really, so long as its got some text. 
       * no reason being all snotty about a spec, right? 
       */
      else if(el->name && el->text.len) {
         xReturn = XMLRPC_CreateValueString(el->name, el->text.str, el->text.len);
      }
   }

   return xReturn;
}

Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 458 of file xmlrpc_introspection.c.

                                                                                      {
   XMLRPC_VALUE xReturn = NULL;
   xml_element* root = xml_elem_parse_buf(xml, 0, 0, err ? &err->xml_elem_error : NULL);

   if(root) {
      xReturn = xml_element_to_method_description(root, err);

      xml_elem_free(root);
   }

   return xReturn;

}

Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 500 of file xmlrpc_introspection.c.

                                                                               {
   int bSuccess = 0;
   if(server && desc) {
      XMLRPC_VALUE xNewTypes = XMLRPC_VectorGetValueWithID(desc, "typeList");
      XMLRPC_VALUE xNewMethods = XMLRPC_VectorGetValueWithID(desc, "methodList");
      XMLRPC_VALUE xServerTypes = XMLRPC_VectorGetValueWithID(server->xIntrospection, "typeList");

      if(xNewMethods) {
         XMLRPC_VALUE xMethod = XMLRPC_VectorRewind(xNewMethods);

         while(xMethod) {
            const char* name = XMLRPC_VectorGetStringWithID(xMethod, xi_token_name);
            server_method* sm = find_method(server, name);

            if(sm) {
               if(sm->desc) {
                  XMLRPC_CleanupValue(sm->desc);
               }
               sm->desc = XMLRPC_CopyValue(xMethod);
               bSuccess = 1;
            }

            xMethod = XMLRPC_VectorNext(xNewMethods);
         }
      }
      if(xNewTypes) {
         if(!xServerTypes) {
            if(!server->xIntrospection) {
               server->xIntrospection = XMLRPC_CreateVector(NULL, xmlrpc_vector_struct);
            }

            XMLRPC_AddValueToVector(server->xIntrospection, xNewTypes);
            bSuccess = 1;
         }
         else {
            XMLRPC_VALUE xIter = XMLRPC_VectorRewind(xNewTypes);
            while(xIter) {
               /* get rid of old values */
               XMLRPC_VALUE xPrev = find_named_value(xServerTypes, XMLRPC_VectorGetStringWithID(xIter, xi_token_name));
               if(xPrev) {
                  XMLRPC_VectorRemoveValue(xServerTypes, xPrev);
               }
               XMLRPC_AddValueToVector(xServerTypes, xIter);
               bSuccess = 1;
               xIter = XMLRPC_VectorNext(xNewTypes);
            }
         }
      }
   }
   return bSuccess;
}

Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 577 of file xmlrpc_introspection.c.

                                                                                                      {
   int bSuccess = 0;
   if(server && cb) {

      doc_method* dm = calloc(1, sizeof(doc_method));
      
      if(dm) {
         dm->method = cb;
         dm->b_called = 0;

         if(Q_PushTail(&server->docslist, dm)) {
            bSuccess = 1;
         }
         else {
            my_free(dm);
         }
      }
   }
   return 0;
}

Here is the call graph for this function:

Here is the caller graph for this function: