Exemple #1
0
/* input: an XMLRPC_VALUE representing a fault struct in xml-rpc style.
 * output: an XMLRPC_VALUE representing a fault struct in soap style,
 *  with xmlrpc codes mapped to soap codes, and all other values preserved.
 *  note that the returned value is a completely new value, and must be freed.
 *  the input value is untouched.
 */
static XMLRPC_VALUE gen_fault_xmlrpc(XMLRPC_VALUE node, xml_element* el_target) {
	XMLRPC_VALUE xDup = XMLRPC_DupValueNew(node);
	XMLRPC_VALUE xCode = XMLRPC_VectorGetValueWithID(xDup, TOKEN_XMLRPC_FAULTCODE);
	XMLRPC_VALUE xStr = XMLRPC_VectorGetValueWithID(xDup, TOKEN_XMLRPC_FAULTSTRING);

	XMLRPC_SetValueID(xCode, TOKEN_SOAP_FAULTCODE, 0);
	XMLRPC_SetValueID(xStr, TOKEN_SOAP_FAULTSTRING, 0);

	/* rough mapping of xmlrpc fault codes to soap codes */
	switch (XMLRPC_GetValueInt(xCode)) {
	case -32700:		  /* "parse error. not well formed", */
	case -32701:		  /* "parse error. unsupported encoding" */
	case -32702:		  /* "parse error. invalid character for encoding" */
	case -32600:		  /* "server error. invalid xml-rpc.  not conforming to spec." */
	case -32601:		  /* "server error. requested method not found" */
	case -32602:		  /* "server error. invalid method parameters" */
		XMLRPC_SetValueString(xCode, "SOAP-ENV:Client", 0);
		break;
	case -32603:		  /* "server error. internal xml-rpc error" */
	case -32500:		  /* "application error" */
	case -32400:		  /* "system error" */
	case -32300:		  /* "transport error */
		XMLRPC_SetValueString(xCode, "SOAP-ENV:Server", 0);
		break;
	}
	return xDup;
}
/* 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;
}
Exemple #3
0
/* determines whether a node is a fault or not, and of which type:
 * 0 = not a fault,
 * 1 = xmlrpc style fault
 * 2 = soap style fault.
 */
static inline int get_fault_type(XMLRPC_VALUE node) {
	if (XMLRPC_VectorGetValueWithID(node, TOKEN_XMLRPC_FAULTCODE) &&
		 XMLRPC_VectorGetValueWithID(node, TOKEN_XMLRPC_FAULTSTRING)) {
		return 1;
	}
	else if (XMLRPC_VectorGetValueWithID(node, TOKEN_SOAP_FAULTCODE) &&
				XMLRPC_VectorGetValueWithID(node, TOKEN_SOAP_FAULTSTRING)) {
		return 2;
	}
	return 0;
}
Exemple #4
0
    // STATIC
    ProtocolUtilities::BuddyListPtr BuddyListParser::ExtractBuddyListFromXMLRPCReply(XmlRpcEpi &call)
    {
        XmlRpcCall *xmlrpcCall = call.GetXMLRPCCall();
        if (!xmlrpcCall)
            throw XmlRpcException("Failed to read buddy list, no XMLRPC Reply to read!");

        XMLRPC_REQUEST request = xmlrpcCall->GetReply();
        if (!request)
            throw XmlRpcException("Failed to read buddy list, no XMLRPC Reply to read!");

        XMLRPC_VALUE result = XMLRPC_RequestGetData(request);
        if (!result)
            throw XmlRpcException("Failed to read buddy list, the XMLRPC Reply did not contain any data!");

        XMLRPC_VALUE buddy_list_node = XMLRPC_VectorGetValueWithID(result, "buddy-list");

        if (!buddy_list_node || XMLRPC_GetValueType(buddy_list_node) != xmlrpc_vector)
            throw XmlRpcException("Failed to read buddy list, buddy-list in the reply was not properly formed!");

        ProtocolUtilities::BuddyListPtr buddy_list = ProtocolUtilities::BuddyListPtr(new ProtocolUtilities::BuddyList());

        XMLRPC_VALUE item = XMLRPC_VectorRewind(buddy_list_node);

        while(item)
        {
            XMLRPC_VALUE_TYPE type = XMLRPC_GetValueType(item);
            if (type == xmlrpc_vector) // xmlrpc-epi handles structs as arrays.
            {
                RexUUID id;
                int rights_given = 0;
                int rights_has = 0;

                XMLRPC_VALUE val = XMLRPC_VectorGetValueWithID(item, "buddy_id");
                if (val && XMLRPC_GetValueType(val) == xmlrpc_string)
                    id.FromString( XMLRPC_GetValueString(val) );

                val = XMLRPC_VectorGetValueWithID(item, "buddy_rights_given");
                if (val && XMLRPC_GetValueType(val) == xmlrpc_type_int)
                    rights_given = XMLRPC_GetValueInt(val);

                val = XMLRPC_VectorGetValueWithID(item, "buddy_rights_has");
                if (val && XMLRPC_GetValueType(val) == xmlrpc_type_int)
                    rights_has = XMLRPC_GetValueInt(val);

                ProtocolUtilities::Buddy *buddy = new ProtocolUtilities::Buddy(id, rights_given, rights_has);
                buddy_list->AddBuddy(buddy);
            }

            item = XMLRPC_VectorNext(buddy_list_node);
        }

        return buddy_list;
    }
/****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;
}
Exemple #6
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;
}
/*
 * This handler takes a single parameter, a struct, that models a daily 
 * calendar.  At the top level, there is one struct for each year.  Each year 
 * is broken down into months, and months into days.  Most of the days are 
 * empty in the struct you receive, but the entry for April 1, 2000 contains 
 * a least three elements named moe, larry and curly, all <i4>s.  Your 
 * handler must add the three numbers and return the result.  
 * 
 * Ken MacLeod: "This description isn't clear, I expected '2000.April.1' when 
 * in fact it's '2000.04.01'.  Adding a note saying that month and day are 
 * two-digits with leading 0s, and January is 01 would help." Done.  
 */
XMLRPC_VALUE validator1_nestedStructTest (XMLRPC_SERVER server, XMLRPC_REQUEST xRequest, void* userData) {
   XMLRPC_VALUE xReturn = NULL; 
   XMLRPC_VALUE xParams = XMLRPC_RequestGetData(xRequest);

   int iSum = 0;

   XMLRPC_VALUE xStruct = XMLRPC_VectorRewind(xParams);
   XMLRPC_VALUE xYear = XMLRPC_VectorGetValueWithID(xStruct, "2000");
   XMLRPC_VALUE xMonth = XMLRPC_VectorGetValueWithID(xYear, "04");
   XMLRPC_VALUE xDay = XMLRPC_VectorGetValueWithID(xMonth, "01");

   iSum += XMLRPC_VectorGetIntWithID(xDay, "larry");
   iSum += XMLRPC_VectorGetIntWithID(xDay, "curly");
   iSum += XMLRPC_VectorGetIntWithID(xDay, "moe");

   xReturn = XMLRPC_CreateValueInt(0, iSum);

   return xReturn;
}
/* system.describeMethods() callback */
static XMLRPC_VALUE xi_system_describe_methods_cb(XMLRPC_SERVER server, XMLRPC_REQUEST input, void* userData) {
   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;
}
LLXMLRPCValue LLXMLRPCValue::operator[](const char* id) const
{
	return LLXMLRPCValue(XMLRPC_VectorGetValueWithID(mV, id));
}
Exemple #10
0
xml_element* XMLRPC_to_xml_element_worker(XMLRPC_VALUE current_vector, XMLRPC_VALUE node, 
                                          XMLRPC_REQUEST_TYPE request_type, int depth) {
#define BUF_SIZE 512
   xml_element* root = NULL;
   if (node) {
      char buf[BUF_SIZE];
      XMLRPC_VALUE_TYPE type = XMLRPC_GetValueType(node);
      XMLRPC_VECTOR_TYPE vtype = XMLRPC_GetVectorType(node);
      xml_element* elem_val = xml_elem_new();

      /* special case for when root element is not an array */
      if (depth == 0 && 
          !(type == xmlrpc_vector && 
            vtype == xmlrpc_vector_array && 
            request_type == xmlrpc_request_call) ) {
         int bIsFault = (vtype == xmlrpc_vector_struct && XMLRPC_VectorGetValueWithID(node, ELEM_FAULTCODE));

         xml_element* next_el = XMLRPC_to_xml_element_worker(NULL, node, request_type, depth + 1);
         if (next_el) {
            Q_PushTail(&elem_val->children, next_el);
         }
         elem_val->name = strdup(bIsFault ? ELEM_FAULT : ELEM_PARAMS);
		}
		else {
         switch (type) {
			case xmlrpc_empty: /*  treat null value as empty string in xmlrpc. */
         case xmlrpc_string:
            elem_val->name = strdup(ELEM_STRING);
            simplestring_addn(&elem_val->text, XMLRPC_GetValueString(node), XMLRPC_GetValueStringLen(node));
            break;
         case xmlrpc_int:
            elem_val->name = strdup(ELEM_INT);
            snprintf(buf, BUF_SIZE, "%i", XMLRPC_GetValueInt(node));
            simplestring_add(&elem_val->text, buf);
            break;
         case xmlrpc_boolean:
            elem_val->name = strdup(ELEM_BOOLEAN);
            snprintf(buf, BUF_SIZE, "%i", XMLRPC_GetValueBoolean(node));
            simplestring_add(&elem_val->text, buf);
            break;
         case xmlrpc_double:
            elem_val->name = strdup(ELEM_DOUBLE);
            snprintf(buf, BUF_SIZE, "%f", XMLRPC_GetValueDouble(node));
            simplestring_add(&elem_val->text, buf);
            break;
         case xmlrpc_datetime:
            elem_val->name = strdup(ELEM_DATETIME);
            simplestring_add(&elem_val->text, XMLRPC_GetValueDateTime_ISO8601(node));
            break;
         case xmlrpc_base64:
            {
               struct buffer_st buf;
               elem_val->name = strdup(ELEM_BASE64);
               base64_encode(&buf, XMLRPC_GetValueBase64(node), XMLRPC_GetValueStringLen(node));
               simplestring_addn(&elem_val->text, buf.data, buf.offset );
               buffer_delete(&buf);
            }
            break;
         case xmlrpc_vector:
            {
               XMLRPC_VECTOR_TYPE my_type = XMLRPC_GetVectorType(node);
               XMLRPC_VALUE xIter = XMLRPC_VectorRewind(node);
               xml_element* root_vector_elem = elem_val;

               switch (my_type) {
               case xmlrpc_vector_array:
                  {
                      if(depth == 0) {
                         elem_val->name = strdup(ELEM_PARAMS);
                      }
                      else {
                         /* Hi my name is Dave and I like to make things as confusing
                          * as possible, thus I will throw in this 'data' element
                          * where it absolutely does not belong just so that people
                          * cannot code arrays and structs in a similar and straight
                          * forward manner. Have a good day.
                          *
                          * GRRRRRRRRR!
                          */
                         xml_element* data = xml_elem_new();
                         data->name = strdup(ELEM_DATA);
    
                         elem_val->name = strdup(ELEM_ARRAY);
                         Q_PushTail(&elem_val->children, data);
                         root_vector_elem = data;
                      }
                  }
                  break;
               case xmlrpc_vector_mixed:       /* not officially supported */
               case xmlrpc_vector_struct:
                  elem_val->name = strdup(ELEM_STRUCT);
                  break;
               default:
                  break;
               }

               /* recurse through sub-elements */
               while ( xIter ) {
                  xml_element* next_el = XMLRPC_to_xml_element_worker(node, xIter, request_type, depth + 1);
                  if (next_el) {
                     Q_PushTail(&root_vector_elem->children, next_el);
                  }
                  xIter = XMLRPC_VectorNext(node);
               }
            }
            break;
         default:
            break;
         }
      }

      {
         XMLRPC_VECTOR_TYPE vtype = XMLRPC_GetVectorType(current_vector);

         if (depth == 1) {
            xml_element* value = xml_elem_new();
            value->name = strdup(ELEM_VALUE);

            /* yet another hack for the "fault" crap */
            if (XMLRPC_VectorGetValueWithID(node, ELEM_FAULTCODE)) {
               root = value;
				}
				else {
               xml_element* param = xml_elem_new();
               param->name = strdup(ELEM_PARAM);

               Q_PushTail(&param->children, value);

               root = param;
            }
            Q_PushTail(&value->children, elem_val);
			}
			else if (vtype == xmlrpc_vector_struct || vtype == xmlrpc_vector_mixed) {
            xml_element* member = xml_elem_new();
            xml_element* name = xml_elem_new();
            xml_element* value = xml_elem_new();

            member->name = strdup(ELEM_MEMBER);
            name->name = strdup(ELEM_NAME);
            value->name = strdup(ELEM_VALUE);

            simplestring_add(&name->text, XMLRPC_GetValueID(node));

            Q_PushTail(&member->children, name);
            Q_PushTail(&member->children, value);
            Q_PushTail(&value->children, elem_val);

            root = member;
			}
			else if (vtype == xmlrpc_vector_array) {
            xml_element* value = xml_elem_new();

            value->name = strdup(ELEM_VALUE);

            Q_PushTail(&value->children, elem_val);

            root = value;
			}
			else if (vtype == xmlrpc_vector_none) {
            /* no parent.  non-op */
            root = elem_val;
			}
			else {
            xml_element* value = xml_elem_new();

            value->name = strdup(ELEM_VALUE);

            Q_PushTail(&value->children, elem_val);

            root = value;
         }
      }
   }
   return root;
}