/* this complies with system.methodSignature as defined at 
 * http://xmlrpc.usefulinc.com/doc/sysmethodsig.html 
 */
static XMLRPC_VALUE xi_system_method_signature_cb(XMLRPC_SERVER server, XMLRPC_REQUEST input, void* userData) {
   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;
}
/****f* SERVER/XMLRPC_ServerAddIntrospectionData
 * NAME
 *   XMLRPC_ServerAddIntrospectionData
 * SYNOPSIS
 *   int XMLRPC_ServerAddIntrospectionData(XMLRPC_SERVER server, XMLRPC_VALUE desc)
 * FUNCTION
 *   updates server with additional introspection data
 * INPUTS
 *   server - target server
 *   desc - introspection data, should be a struct generated by 
 *          XMLRPC_IntrospectionCreateDescription ()
 * RESULT
 *   int - 1 if success, else 0
 * NOTES
 *  - function will fail if neither typeList nor methodList key is present in struct.
 *  - if method or type already exists, it will be replaced.
 *  - desc is never freed by the server.  caller is responsible for cleanup.
 * BUGS
 *   - horribly slow lookups. prime candidate for hash improvements.
 *   - uglier and more complex than I like to see for API functions.
 * SEE ALSO
 *   XMLRPC_ServerAddIntrospectionData ()
 *   XMLRPC_ServerRegisterIntrospectionCallback ()
 *   XMLRPC_CleanupValue ()
 * SOURCE
 */
int XMLRPC_ServerAddIntrospectionData(XMLRPC_SERVER server, XMLRPC_VALUE desc) {
   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;
}
Beispiel #3
0
XMLRPC_VALUE xsm_system_multicall_cb(XMLRPC_SERVER server, XMLRPC_REQUEST input, void* userData) {
   XMLRPC_VALUE xArray = XMLRPC_VectorRewind(XMLRPC_RequestGetData(input));
   XMLRPC_VALUE xReturn = XMLRPC_CreateVector(0, xmlrpc_vector_array);

   if (xArray) {
      XMLRPC_VALUE xMethodIter = XMLRPC_VectorRewind(xArray);

      while (xMethodIter) {
         XMLRPC_REQUEST request = XMLRPC_RequestNew();
         if(request) {
            const char* methodName = XMLRPC_VectorGetStringWithID(xMethodIter, "methodName");
            XMLRPC_VALUE params = XMLRPC_VectorGetValueWithID(xMethodIter, "params");

            if(methodName && params) {
               XMLRPC_VALUE xRandomArray = XMLRPC_CreateVector(0, xmlrpc_vector_array);
               XMLRPC_RequestSetMethodName(request, methodName);
               XMLRPC_RequestSetData(request, params);
               XMLRPC_RequestSetRequestType(request, xmlrpc_request_call);

               XMLRPC_AddValueToVector(xRandomArray, 
                                       XMLRPC_ServerCallMethod(server, request, userData));

               XMLRPC_AddValueToVector(xReturn, xRandomArray);
            }
            XMLRPC_RequestFree(request, 1);
         }
         xMethodIter = XMLRPC_VectorNext(xArray);
      }
   }
   return xReturn;
}
/* iterates through a list of structs and finds the one with key "name" matching
 * needle.  slow, would benefit from a struct key hash.
 */
static inline XMLRPC_VALUE find_named_value(XMLRPC_VALUE list, const char* needle) {
   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;
}
/* this complies with system.methodHelp as defined at 
 * http://xmlrpc.usefulinc.com/doc/sysmethhelp.html 
 */
static XMLRPC_VALUE xi_system_method_help_cb(XMLRPC_SERVER server, XMLRPC_REQUEST input, void* userData) {
   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;
}