Logo Search packages:      
Sourcecode: gambas version File versions  Download package

CXmlRpc.c

/***************************************************************************

  CXmlRpc.c

  XML-RPC client

  (c) 2004 Daniel Campos Fernández <danielcampos@netcourrier.com> 

  This program is free software; you can redistribute it and/or modify
  it under the terms of the GNU General Public License as published by
  the Free Software Foundation; either version 1, or (at your option)
  any later version.

  This program is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  GNU General Public License for more details.

  You should have received a copy of the GNU General Public License
  along with this program; if not, write to the Free Software
  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.

***************************************************************************/



#define __CXMLRPC_C

#include <stdio.h>
#include <libxml/xmlreader.h>
#include <libxml/xmlwriter.h>
#include "main.h"
#include "string.h"
#include "CXmlRpc.h"


BEGIN_METHOD_VOID(CXMLRPC_Free)

      if (THIS->parameters) GB.Free((void**)&THIS->parameters);

END_METHOD

BEGIN_METHOD(CXMLRPC_New,GB_INTEGER RpcType;GB_STRING MethodName;GB_OBJECT Parameters;GB_INTEGER ReturnType;)

      int myloop;
      int nmax;
      int rtype;
      
      if ( (VARG(RpcType)<0) || (VARG(RpcType)>2) )
      {
            GB.Error("Invalid RPC Type");
            return;
      }
      //TODO
      if (VARG(RpcType)!=0)
      {
            GB.Error("Unimplemented RPC Type, this is alpha software, sorry");
            return;
      }
      //
      THIS->type=VARG(RpcType);
            
      nmax=GB.Array.Count(VARG(Parameters));
      
      if (MISSING(ReturnType))
      {
            THIS->returntype=-1;
      }
      else
      {
            if ( (VARG(ReturnType)<0) || (VARG(ReturnType)>7) )
            {
                  GB.Error("Invalid return type");
                  return;
            }
            THIS->returntype=VARG(ReturnType);
      }
      
      if (LENGTH(MethodName))
      {
            if (nmax)
            {
                  for (myloop=0;myloop<nmax;myloop++)
                  {
                        rtype=*((int*)GB.Array.Get(VARG(Parameters),myloop)); 
                        if (rtype<0 || rtype>7)
                        {
                                    GB.Error("Unknown RPC data type");
                                    return;
                        }
                  }
                  
                  THIS->nparams=nmax;
                  GB.Alloc ((void**)&THIS->parameters,sizeof(int)*nmax);
                  for (myloop=0;myloop<nmax;myloop++)
                        THIS->parameters[myloop]=*((int*)GB.Array.Get(VARG(Parameters),myloop)); 

            }
            
            THIS->name=GB.ToZeroString(ARG(MethodName));
            return;
      }
      
      GB.Error("Invalid RPC method name");
      

END_METHOD


BEGIN_METHOD(CXMLRPC_Call,GB_VALUE param[0];)

      double value;
      char *cname; 
      char *buf;
      int bucle;
      long len;
      int myok=1;
      GB_VALUE *args=ARG(param[0]);
      xmlTextWriterPtr writer;
      xmlBufferPtr buffer;
      
      if (THIS->nparams != GB.NParam())
      {
            GB.Error ("Wrong RPC parameters number");
            return;
      }
      
      
      for(bucle=0;bucle<THIS->nparams;bucle++)
      {
            switch(THIS->parameters[bucle])
            {
                  case 0: if ( args[bucle].type != GB_T_BOOLEAN) myok=0; break;
                  case 1: if ( args[bucle].type != GB_T_INTEGER) myok=0; break;
                  case 2: if ( args[bucle].type != GB_T_FLOAT) myok=0; break;
                  case 3: if ( args[bucle].type != GB_T_STRING) myok=0; break;
                  case 4: if ( args[bucle].type != GB_T_DATE) myok=0; break;
                  case 5: if ( args[bucle].type != GB_T_STRING) myok=0; break;
                  case 6: break;// TODO: array
                  case 7: break;// TODO: struct
            }
            
            if (!myok) break;
      }
      
      if (!myok)
      {
            GB.Error("Wrong Parameter Type");
            return;
      }
      
      
      buffer=xmlBufferCreate();
      writer=xmlNewTextWriterMemory(buffer, 0);
      xmlTextWriterSetIndent(writer,1);   
      xmlTextWriterStartDocument(writer, NULL,"UTF-8", NULL);
      
      xmlTextWriterStartElement (writer,"methodCall");
      xmlTextWriterWriteElement (writer,"methodName",THIS->name);
      
      xmlTextWriterStartElement (writer,"params");
      
      for(bucle=0;bucle<THIS->nparams;bucle++)
      {
      
        xmlTextWriterStartElement (writer,"param");
        xmlTextWriterStartElement (writer,"value");
       
        switch(THIS->parameters[bucle])
        {
            case 0: // Boolean      
                  if (((GB_BOOLEAN*)args)[bucle].value) 
                        xmlTextWriterWriteElement(writer,"boolean","1");
                  else 
                        xmlTextWriterWriteElement(writer,"boolean","0");
                  break;
                  
            case 1:
                  value=((GB_INTEGER*)args)[bucle].value;
                  GB.NumberToString (0,value,NULL,&buf,&len);
                  xmlTextWriterWriteElement(writer,"i4",buf);
                  break;
            
            case 2:
                  value=((GB_FLOAT*)args)[bucle].value;
                  GB.NumberToString (0,value,NULL,&buf,&len);
                  xmlTextWriterWriteElement(writer,"double",buf);
                  break;
                  
            case 3:
                  //buf=GB.ToZeroString(   );
                  xmlTextWriterWriteElement(writer,"string",((GB_STRING*)args)[bucle].value.addr);
                  break;
                  
            case 4:break;
            case 5:break;
            case 6: break;//TODO Array
            case 7: break;//TODO STRUCT   
        }
      
        
        xmlTextWriterEndElement (writer);
        xmlTextWriterEndElement (writer);
      }

      xmlTextWriterEndDocument(writer);
      xmlFreeTextWriter(writer);
      
      if (THIS->type == 0)
      {
            GB.ReturnNewString(buffer->content,0);
            return;
      }
      
      
      xmlBufferFree(buffer);
      


END_METHOD


BEGIN_METHOD(CXMLRPC_SetReply,GB_STRING Reply;)

      THIS->reply=GB.ToZeroString(ARG(Reply));

END_METHOD

 


/*

int rpc_search(xmlTextReaderPtr reader,char *name,char *name2)
{
      int depth;
      int ndepth;
      int retval;
      
      if (xmlTextReaderRead(reader)!=1) return -1;
      
      depth=xmlTextReaderDepth(reader);
      ndepth=depth;
      
      do 
      {
            if (xmlTextReaderNodeType(reader)==XML_READER_TYPE_ELEMENT)
            {
                  ndepth++;
                  
                  if (!name) return 1;
                  
                  if ( strcmp(xmlTextReaderName(reader),name)==0) 
                        if (ndepth==(depth+1)) return 1;
                        
                  if (name2)
                  {
                        if ( strcmp(xmlTextReaderName(reader),name2)==0) 
                              if (ndepth==(depth+1)) return 1;
                  }
      
            }
            
            if (xmlTextReaderNodeType(reader)==XML_READER_TYPE_END_ELEMENT)
            {
                  ndepth--;
                  if (ndepth<depth) return 0;
            }
      
      
            retval=xmlTextReaderRead(reader);
            
      } while (retval==1);
      
      return 0;   
}


void rpc_fault(xmlTextReaderPtr reader)
{
      xmlNodePtr node;
      int fc=0,fd=0;
      char *content;

      if (rpc_search(reader,"value",NULL)!=1)
      {
            GB.Error("Unable to parse XML reply"); 
            return;
      }
      if (rpc_search(reader,"struct",NULL)!=1)
      {
            GB.Error("Unable to parse XML reply"); 
            return;
      }
      
      node=xmlTextReaderExpand(reader);
      content=xmlNodeGetContent(node);
      
      if (!content)
      {
            GB.Error("Unable to parse XML reply"); 
            return;
      }
      
      GB.Error(content);
      free(content);
      return;
}

int rpc_eval_return_type(xmlTextReaderPtr reader)
{
      int rtype=-1;
      
      do 
      {
            switch(xmlTextReaderRead(reader))
            {
                  case 1:
                        switch(xmlTextReaderNodeType(reader))
                  
                  
                  default: return -1;
            }
            
      } while (1)
      

            
      if ( xmlTextReaderNodeType(reader)==XML_READER_TYPE_ELEMENT)
      {
            if (strcmp(xmlTextReaderName(reader),"boolean")==0) rtype=0;
            if (strcmp(xmlTextReaderName(reader),"i4")==0) rtype=1;
            if (strcmp(xmlTextReaderName(reader),"int")==0) rtype=1;
            if (strcmp(xmlTextReaderName(reader),"double")==0) rtype=2;
            if (strcmp(xmlTextReaderName(reader),"string")==0) rtype=3;
            if (strcmp(xmlTextReaderName(reader),"dateTime.iso8601")==0) rtype=4;
            if (strcmp(xmlTextReaderName(reader),"base64")==0) rtype=5;
            if (strcmp(xmlTextReaderName(reader),"struct")==0) rtype=6;
            if (strcmp(xmlTextReaderName(reader),"array")==0) rtype=7;  
      }
      else
      {
            rtype=0;
      }
      
      
      return rtype;
}

BEGIN_METHOD_VOID(CXMLRPC_GetReturn)

      xmlTextReaderPtr reader=NULL;
      int retval=1;
      int rtype=-1;
      
      if (THIS->reply) reader=xmlReaderForMemory(THIS->reply,strlen(THIS->reply),"",NULL,0);
      
      if (!reader) { GB.Error("Unable to parse XML reply"); return; }
      
      if (rpc_search(reader,"methodResponse",NULL)!=1) { GB.Error("Unable to parse XML reply"); return; }
      
      retval=rpc_search(reader,"params","fault");
      
      switch (retval)
      {
            case 0: 
                  return;
            case 1:
                  if ( strcmp(xmlTextReaderName(reader),"fault")==0)
                  {
                        rpc_fault(reader);
                        return;
                  }
                  
                  if (rpc_search(reader,"param",NULL)!=1)
                  {
                        GB.Error("Unable to parse XML reply"); 
                        return;
                  }
                  
                  if (rpc_search(reader,"value",NULL)!=1)
                  {
                        GB.Error("Unable to parse XML reply"); 
                        return;
                  }
                  break;
                  
                  
            default: 
                  GB.Error("Unable to parse XML reply"); return;
            
            
      }
      
      
      
      


END_METHOD
*/

GB_DESC CXmlRpcTypeDesc[] =
{
      GB_DECLARE("RpcType",0), GB_NOT_CREATABLE(),
      
      GB_CONSTANT("RpcAsyncHttp","i",2),
      GB_CONSTANT("RpcSyncHttp","i",1),
      GB_CONSTANT("RpcString","i",0),
      
      GB_CONSTANT("Boolean","i",0),
      GB_CONSTANT("Integer","i",1),
      GB_CONSTANT("Double","i",2),
      GB_CONSTANT("String","i",3),
      GB_CONSTANT("Date","i",4),
      GB_CONSTANT("Base64","i",5),
      GB_CONSTANT("Array","i",6),
      GB_CONSTANT("Struct","i",7),
      
      GB_END_DECLARE
};



GB_DESC CXmlRpcDesc[] =
{
  GB_DECLARE("XmlRpc", sizeof(CXMLRPC)),
  
  GB_METHOD("_new",NULL,CXMLRPC_New,"(RpcType)i(MethodName)s(Parameters)Integer[];[(ReturnType)i]"),
  GB_METHOD("_free",NULL,CXMLRPC_Free,NULL),
  
  GB_METHOD( "_call" ,"v", CXMLRPC_Call ,"."), 
  
  //GB_METHOD("SetReply",NULL,CXMLRPC_SetReply,"(ServerReply)s"),
  //GB_METHOD("GetReturnValue","v",CXMLRPC_GetReturn,NULL),

  GB_END_DECLARE
};





Generated by  Doxygen 1.6.0   Back to index