Don't click here unless you want to be banned.

LSL Wiki : XMLRPCImplementations

HomePage :: PageIndex :: RecentChanges :: RecentlyCommented :: UserSettings :: You are crawl338.us.archive.org
Here you'll find some XML-RPC sample implementations in various languages:

Language: Modules/Libraries Used:
ASP aspxmlrpc
C# System.Web
C++ Example 1 XmlRpc++ (Modified)
C++ Example 2 KDE 3.x (Linux)
Java Apache XML-RPC
JavaScript JavaScript O Lait
Perl RPC::XML
PHP Example 1 XML-RPC
PHP Example 2 XML-RPC
Python Example 1 xmlrpclib
Python Example 2 python-xmlrpc
Ruby xmlrpc4r

FYI: XML assumes UTF-8 as the encoding type if not otherwise speficied (like in XML-RPC), in your software you should expect UTF-8 strings when parsing results. SL uses UTF-8 for it's encoding of strings.




ASP


This ASP example uses the aspxmlrpc http://aspxmlrpc.sourceforge.net/ library by David Carter-Tod, et. al..

<%

Dim paramList(0)
Set paramList(0) = CreateObject("Scripting.Dictionary")
paramList(0).Add "Channel","0d58c21c-b56f-57df-745f-9ccd0e06df49"
paramList(0).Add "IntValue",CByte(17)
paramList(0).Add "StringValue","Hello, Alexander!"

Dim myresp
on error resume next
Set myresp = xmlRPC("http://xmlrpc.secondlife.com/cgi-bin/xmlrpc.cgi", "llRemoteData", paramList)
on error goto 0

if err.number <>0 then
	response.write("Error number: " & err.number & "<P>")
	response.write("Error description: " & err.description & "<P>")
else
	response.write("Channel: " & myresp("Channel") & vbCrLf)
	response.write("IntValue: " & myresp("IntValue") & vbCrLf)
	response.write("StringValue: " & myresp("StringValue") & vbCrLf)
end if

%>




C#

C# Implementation by DedricMauriac. Make sure to add a reference to System.Web in your project.

using System;
using System.IO;
using System.Net;
using System.Text;
using System.Text.RegularExpressions;
using System.Diagnostics;
using System.Web;

/*
 * XmlRpc rpc = new XmlRpc(
 *      new Guid("ba70440d-7d8b-cd1e-db1c-198d563bae55"),
 *      "This is some text",
 *      42);
 * rpc.llRemoteData();
 * Debug.WriteLine(rpc.channel, "channel");
 * Debug.WriteLine(rpc.stringValue, "string");
 * Debug.WriteLine(rpc.intValue, "int");
 */

public class XmlRpc
{
    private const string MethodCallTemplate = @"<?xml version=""1.0""?><methodCall><methodName>llRemoteData</methodName><params><param><value><struct><member><name>Channel</name><value><string>{0}</string></value></member><member><name>IntValue</name><value><int>{1}</int></value></member><member><name>StringValue</name><value><string>{2}</string></value></member></struct></value></param></params></methodCall>";

    public Guid channel;
    public string stringValue;
    public int intValue;
    public bool TimedOut;

    public XmlRpc()
    {
    }
    public XmlRpc(Guid channel, string stringValue, int intValue)
    {
        this.channel = channel;
        this.stringValue = stringValue;
        this.intValue = intValue;
    }

    public void llRemoteData()
    {
        string methodCall = string.Format(MethodCallTemplate, 
            this.channel, 
            this.intValue, 
            HttpUtility.HtmlEncode(this.stringValue)
            );

        Uri requestUri = new Uri("http://xmlrpc.secondlife.com/cgi-bin/xmlrpc.cgi");
        
        string methodResponse = Post(requestUri, methodCall);
        
        ParseResponse(methodResponse);
    }

    private void ParseResponse(string methodResponse)
    {
        if (methodResponse.IndexOf("<fault>") != -1)
        {
            string message = Regex.Match(methodResponse,
                "<value><string>([^>]+)</string></value>")
                .Groups[1].Value;
            throw new ApplicationException(message);
        }

        MatchCollection matches = Regex.Matches(methodResponse, @"<name>([^<]+)</name>\s*<value>\s*<(string|int)>([^<]+)</\2>\s*</value>");
        foreach (Match match in matches)
        {
            string name = match.Groups[1].Value;
            string value = match.Groups[3].Value;
            switch (name)
            {
                case "Channel":
                    this.channel = new Guid(value);
                    break;
                case "StringValue":
                    this.stringValue = HttpUtility.HtmlDecode(value);
                    break;
                case "IntValue":
                    this.intValue = int.Parse(value);
                    break;
            }
        }
    }
    private string Post(Uri requestUri, string data)
    {
        TimedOut = false;
        byte[] postData = ASCIIEncoding.Default.GetBytes(data);
        HttpWebRequest request = null;
        Stream writer = null;
        Stream reader = null;
        WebResponse response = null;
        try
        {
            request = HttpWebRequest.Create(requestUri) as HttpWebRequest;

            request.Method = "POST";
            request.KeepAlive = false;
            request.ContentType = "application/x-www-form-urlencoded";
            request.Timeout = 10000;

            request.ContentLength = postData.Length;

            writer = request.GetRequestStream();
            writer.Write(postData, 0, postData.Length);
            writer.Close();

            response = request.GetResponse();

            reader = response.GetResponseStream();
            byte[] postResponse = new byte[response.ContentLength];
            reader.Read(postResponse, 0, postResponse.Length);

            return ASCIIEncoding.Default.GetString(postResponse);
        }
        catch (WebException ex)
        {
            if (ex.Status == WebExceptionStatus.Timeout)
            {
                TimedOut = true;
                return "";
            }
            else
                throw;
        }
        finally
        {
            if (writer != null)
            {
                writer.Close();
                writer.Dispose();
            }
            if (reader != null)
            {
                reader.Close();
                reader.Dispose();
            }
            if (response != null)
            {
                response.Close();
            }
        }
    }
}




C++


This C++ example uses the XmlRpc++ implementation, with some modifications listed below

Modified XmlRpcValue.cpp (v.07)
#include "XmlRpcValue.h"
#include "XmlRpcException.h"
#include "XmlRpcUtil.h"
#include "base64.h"

#ifndef MAKEDEPEND
# include <iostream>
# include <ostream>
# include <stdlib.h>
# include <stdio.h>
#endif

namespace XmlRpc {


  static const char VALUE_TAG[]     = "<value>";
  static const char VALUE_ETAG[]    = "</value>";

  static const char BOOLEAN_TAG[]   = "<boolean>";
  static const char BOOLEAN_ETAG[]  = "</boolean>";
  static const char DOUBLE_TAG[]    = "<double>";
  static const char DOUBLE_ETAG[]   = "</double>";
  static const char INT_TAG[]       = "<int>";
  static const char I4_TAG[]        = "<int>"; /* Was i4 */
  static const char I4_ETAG[]       = "</int>"; /* Was i4 */
  static const char STRING_TAG[]    = "<string>";
  static const char STRING_ETAG[]   = "</string>";
  static const char DATETIME_TAG[]  = "<dateTime.iso8601>";
  static const char DATETIME_ETAG[] = "</dateTime.iso8601>";
  static const char BASE64_TAG[]    = "<base64>";
  static const char BASE64_ETAG[]   = "</base64>";

  static const char ARRAY_TAG[]     = "<array>";
  static const char DATA_TAG[]      = "<data>";
  static const char DATA_ETAG[]     = "</data>";
  static const char ARRAY_ETAG[]    = "</array>";

  static const char STRUCT_TAG[]    = "<struct>";
  static const char MEMBER_TAG[]    = "<member>";
  static const char NAME_TAG[]      = "<name>";
  static const char NAME_ETAG[]     = "</name>";
  static const char MEMBER_ETAG[]   = "</member>";
  static const char STRUCT_ETAG[]   = "</struct>";


      
  // Format strings
  std::string XmlRpcValue::_doubleFormat("%f");



  // Clean up
  void XmlRpcValue::invalidate()
  {
    switch (_type) {
      case TypeString:    delete _value.asString; break;
      case TypeDateTime:  delete _value.asTime;   break;
      case TypeBase64:    delete _value.asBinary; break;
      case TypeArray:     delete _value.asArray;  break;
      case TypeStruct:    delete _value.asStruct; break;
      default: break;
    }
    _type = TypeInvalid;
    _value.asBinary = 0;
  }

  
  // Type checking
  void XmlRpcValue::assertTypeOrInvalid(Type t)
  {
    if (_type == TypeInvalid)
    {
      _type = t;
      switch (_type) {    // Ensure there is a valid value for the type
        case TypeString:   _value.asString = new std::string(); break;
        case TypeDateTime: _value.asTime = new struct tm();     break;
        case TypeBase64:   _value.asBinary = new BinaryData();  break;
        case TypeArray:    _value.asArray = new ValueArray();   break;
        case TypeStruct:   _value.asStruct = new ValueStruct(); break;
        default:           _value.asBinary = 0; break;
      }
    }
    else if (_type != t)
      throw XmlRpcException("type error");
  }

  void XmlRpcValue::assertArray(int size) const
  {
    if (_type != TypeArray)
      throw XmlRpcException("type error: expected an array");
    else if (int(_value.asArray->size()) < size)
      throw XmlRpcException("range error: array index too large");
  }


  void XmlRpcValue::assertArray(int size)
  {
    if (_type == TypeInvalid) {
      _type = TypeArray;
      _value.asArray = new ValueArray(size);
    } else if (_type == TypeArray) {
      if (int(_value.asArray->size()) < size)
        _value.asArray->resize(size);
    } else
      throw XmlRpcException("type error: expected an array");
  }

  void XmlRpcValue::assertStruct()
  {
    if (_type == TypeInvalid) {
      _type = TypeStruct;
      _value.asStruct = new ValueStruct();
    } else if (_type != TypeStruct)
      throw XmlRpcException("type error: expected a struct");
  }


  // Operators
  XmlRpcValue& XmlRpcValue::operator=(XmlRpcValue const& rhs)
  {
    if (this != &rhs)
    {
      invalidate();
      _type = rhs._type;
      switch (_type) {
        case TypeBoolean:  _value.asBool = rhs._value.asBool; break;
        case TypeInt:      _value.asInt = rhs._value.asInt; break;
        case TypeDouble:   _value.asDouble = rhs._value.asDouble; break;
        case TypeDateTime: _value.asTime = new struct tm(*rhs._value.asTime); break;
        case TypeString:   _value.asString = new std::string(*rhs._value.asString); break;
        case TypeBase64:   _value.asBinary = new BinaryData(*rhs._value.asBinary); break;
        case TypeArray:    _value.asArray = new ValueArray(*rhs._value.asArray); break;
        case TypeStruct:   _value.asStruct = new ValueStruct(*rhs._value.asStruct); break;
        default:           _value.asBinary = 0; break;
      }
    }
    return *this;
  }


  // Predicate for tm equality
  static bool tmEq(struct tm const& t1, struct tm const& t2) {
    return t1.tm_sec == t2.tm_sec && t1.tm_min == t2.tm_min &&
            t1.tm_hour == t2.tm_hour && t1.tm_mday == t1.tm_mday &&
            t1.tm_mon == t2.tm_mon && t1.tm_year == t2.tm_year;
  }

  bool XmlRpcValue::operator==(XmlRpcValue const& other) const
  {
    if (_type != other._type)
      return false;

    switch (_type) {
      case TypeBoolean:  return ( !_value.asBool && !other._value.asBool) ||
                                ( _value.asBool && other._value.asBool);
      case TypeInt:      return _value.asInt == other._value.asInt;
      case TypeDouble:   return _value.asDouble == other._value.asDouble;
      case TypeDateTime: return tmEq(*_value.asTime, *other._value.asTime);
      case TypeString:   return *_value.asString == *other._value.asString;
      case TypeBase64:   return *_value.asBinary == *other._value.asBinary;
      case TypeArray:    return *_value.asArray == *other._value.asArray;

      // The map<>::operator== requires the definition of value< for kcc
      case TypeStruct:   //return *_value.asStruct == *other._value.asStruct;
        {
          if (_value.asStruct->size() != other._value.asStruct->size())
            return false;
          
          ValueStruct::const_iterator it1=_value.asStruct->begin();
          ValueStruct::const_iterator it2=other._value.asStruct->begin();
          while (it1 != _value.asStruct->end()) {
            const XmlRpcValue& v1 = it1->second;
            const XmlRpcValue& v2 = it2->second;
            if ( ! (v1 == v2))
              return false;
            it1++;
            it2++;
          }
          return true;
        }
      default: break;
    }
    return true;    // Both invalid values ...
  }

  bool XmlRpcValue::operator!=(XmlRpcValue const& other) const
  {
    return !(*this == other);
  }


  // Works for strings, binary data, arrays, and structs.
  int XmlRpcValue::size() const
  {
    switch (_type) {
      case TypeString: return int(_value.asString->size());
      case TypeBase64: return int(_value.asBinary->size());
      case TypeArray:  return int(_value.asArray->size());
      case TypeStruct: return int(_value.asStruct->size());
      default: break;
    }

    throw XmlRpcException("type error");
  }

  // Checks for existence of struct member
  bool XmlRpcValue::hasMember(const std::string& name) const
  {
    return _type == TypeStruct && _value.asStruct->find(name) != _value.asStruct->end();
  }

  // Set the value from xml. The chars at *offset into valueXml 
  // should be the start of a <value> tag. Destroys any existing value.
  bool XmlRpcValue::fromXml(std::string const& valueXml, int* offset)
  {
    int savedOffset = *offset;

    invalidate();
    if ( ! XmlRpcUtil::nextTagIs(VALUE_TAG, valueXml, offset))
      return false;       // Not a value, offset not updated

 int afterValueOffset = *offset;
    std::string typeTag = XmlRpcUtil::getNextTag(valueXml, offset);
    bool result = false;
    if (typeTag == BOOLEAN_TAG)
      result = boolFromXml(valueXml, offset);
    else if (typeTag == I4_TAG || typeTag == INT_TAG)
      result = intFromXml(valueXml, offset);
    else if (typeTag == DOUBLE_TAG)
      result = doubleFromXml(valueXml, offset);
    else if (typeTag.empty() || typeTag == STRING_TAG)
      result = stringFromXml(valueXml, offset);
    else if (typeTag == DATETIME_TAG)
      result = timeFromXml(valueXml, offset);
    else if (typeTag == BASE64_TAG)
      result = binaryFromXml(valueXml, offset);
    else if (typeTag == ARRAY_TAG)
      result = arrayFromXml(valueXml, offset);
    else if (typeTag == STRUCT_TAG)
      result = structFromXml(valueXml, offset);
    // Watch for empty/blank strings with no <string>tag
    else if (typeTag == VALUE_ETAG)
    {
      *offset = afterValueOffset;   // back up & try again
      result = stringFromXml(valueXml, offset);
    }

    if (result)  // Skip over the </value> tag
      XmlRpcUtil::findTag(VALUE_ETAG, valueXml, offset);
    else        // Unrecognized tag after <value>
      *offset = savedOffset;

    return result;
  }

  // Encode the Value in xml
  std::string XmlRpcValue::toXml() const
  {
    switch (_type) {
      case TypeBoolean:  return boolToXml();
      case TypeInt:      return intToXml();
      case TypeDouble:   return doubleToXml();
      case TypeString:   return stringToXml();
      case TypeDateTime: return timeToXml();
      case TypeBase64:   return binaryToXml();
      case TypeArray:    return arrayToXml();
      case TypeStruct:   return structToXml();
      default: break;
    }
    return std::string();   // Invalid value
  }


  // Boolean
  bool XmlRpcValue::boolFromXml(std::string const& valueXml, int* offset)
  {
    const char* valueStart = valueXml.c_str() + *offset;
    char* valueEnd;
    long ivalue = strtol(valueStart, &valueEnd, 10);
    if (valueEnd == valueStart || (ivalue != 0 && ivalue != 1))
      return false;

    _type = TypeBoolean;
    _value.asBool = (ivalue == 1);
    *offset += int(valueEnd - valueStart);
    return true;
  }

  std::string XmlRpcValue::boolToXml() const
  {
    std::string xml = VALUE_TAG;
    xml += BOOLEAN_TAG;
    xml += (_value.asBool ? "1" : "0");
    xml += BOOLEAN_ETAG;
    xml += VALUE_ETAG;
    return xml;
  }

  // Int
  bool XmlRpcValue::intFromXml(std::string const& valueXml, int* offset)
  {
    const char* valueStart = valueXml.c_str() + *offset;
    char* valueEnd;
    long ivalue = strtol(valueStart, &valueEnd, 10);
    if (valueEnd == valueStart)
      return false;

    _type = TypeInt;
    _value.asInt = int(ivalue);
    *offset += int(valueEnd - valueStart);
    return true;
  }

  std::string XmlRpcValue::intToXml() const
  {
    char buf[256];
    snprintf(buf, sizeof(buf)-1, "%d", _value.asInt);
    buf[sizeof(buf)-1] = 0;
    std::string xml = VALUE_TAG;
    xml += I4_TAG;
    xml += buf;
    xml += I4_ETAG;
    xml += VALUE_ETAG;
    return xml;
  }

  // Double
  bool XmlRpcValue::doubleFromXml(std::string const& valueXml, int* offset)
  {
    const char* valueStart = valueXml.c_str() + *offset;
    char* valueEnd;
    double dvalue = strtod(valueStart, &valueEnd);
    if (valueEnd == valueStart)
      return false;

    _type = TypeDouble;
    _value.asDouble = dvalue;
    *offset += int(valueEnd - valueStart);
    return true;
  }

  std::string XmlRpcValue::doubleToXml() const
  {
    char buf[256];
    snprintf(buf, sizeof(buf)-1, getDoubleFormat().c_str(), _value.asDouble);
    buf[sizeof(buf)-1] = 0;

    std::string xml = VALUE_TAG;
    xml += DOUBLE_TAG;
    xml += buf;
    xml += DOUBLE_ETAG;
    xml += VALUE_ETAG;
    return xml;
  }

  // String
  bool XmlRpcValue::stringFromXml(std::string const& valueXml, int* offset)
  {
    size_t valueEnd = valueXml.find('<', *offset);
    if (valueEnd == std::string::npos)
      return false;     // No end tag;

    _type = TypeString;
    _value.asString = new std::string(XmlRpcUtil::xmlDecode(valueXml.substr(*offset, valueEnd-*offset)));
    *offset += int(_value.asString->length());
    return true;
  }

  std::string XmlRpcValue::stringToXml() const
  {
    std::string xml = VALUE_TAG;
    xml += STRING_TAG;// optional
    xml += XmlRpcUtil::xmlEncode(*_value.asString);
    xml += STRING_ETAG;
    xml += VALUE_ETAG;
    return xml;
  }

  // DateTime (stored as a struct tm)
  bool XmlRpcValue::timeFromXml(std::string const& valueXml, int* offset)
  {
    size_t valueEnd = valueXml.find('<', *offset);
    if (valueEnd == std::string::npos)
      return false;     // No end tag;

    std::string stime = valueXml.substr(*offset, valueEnd-*offset);

    struct tm t;
    if (sscanf(stime.c_str(),"%4d%2d%2dT%2d:%2d:%2d",&t.tm_year,&t.tm_mon,&t.tm_mday,&t.tm_hour,&t.tm_min,&t.tm_sec) != 6)
      return false;

    t.tm_isdst = -1;
    _type = TypeDateTime;
    _value.asTime = new struct tm(t);
    *offset += int(stime.length());
    return true;
  }

  std::string XmlRpcValue::timeToXml() const
  {
    struct tm* t = _value.asTime;
    char buf[20];
    snprintf(buf, sizeof(buf)-1, "%4d%02d%02dT%02d:%02d:%02d", 
      t->tm_year,t->tm_mon,t->tm_mday,t->tm_hour,t->tm_min,t->tm_sec);
    buf[sizeof(buf)-1] = 0;

    std::string xml = VALUE_TAG;
    xml += DATETIME_TAG;
    xml += buf;
    xml += DATETIME_ETAG;
    xml += VALUE_ETAG;
    return xml;
  }


  // Base64
  bool XmlRpcValue::binaryFromXml(std::string const& valueXml, int* offset)
  {
    size_t valueEnd = valueXml.find('<', *offset);
    if (valueEnd == std::string::npos)
      return false;     // No end tag;

    _type = TypeBase64;
    std::string asString = valueXml.substr(*offset, valueEnd-*offset);
    _value.asBinary = new BinaryData();
    // check whether base64 encodings can contain chars xml encodes...

    // convert from base64 to binary
    int iostatus = 0;
   base64<char> decoder;
  decoder.get(asString.begin(), asString.end(), std::back_inserter(*_value.asBinary), iostatus);

    *offset += int(asString.length());
    return true;
  }


  std::string XmlRpcValue::binaryToXml() const
  {
    // convert to base64
    std::vector<char> base64data;
    int iostatus = 0;
   base64<char> encoder;
  encoder.put(_value.asBinary->begin(), _value.asBinary->end(), std::back_inserter(base64data), iostatus, base64<>::crlf());

    // Wrap with xml
    std::string xml = VALUE_TAG;
    xml += BASE64_TAG;
    xml.append(base64data.begin(), base64data.end());
    xml += BASE64_ETAG;
    xml += VALUE_ETAG;
    return xml;
  }


  // Array
  bool XmlRpcValue::arrayFromXml(std::string const& valueXml, int* offset)
  {
    if ( ! XmlRpcUtil::nextTagIs(DATA_TAG, valueXml, offset))
      return false;

    _type = TypeArray;
    _value.asArray = new ValueArray;
    XmlRpcValue v;
    while (v.fromXml(valueXml, offset))
      _value.asArray->push_back(v);       // copy...

    // Skip the trailing </data>
    (void) XmlRpcUtil::nextTagIs(DATA_ETAG, valueXml, offset);
    return true;
  }


  // In general, its preferable to generate the xml of each element of the
  // array as it is needed rather than glomming up one big string.
  std::string XmlRpcValue::arrayToXml() const
  {
    std::string xml = VALUE_TAG;
    xml += ARRAY_TAG;
    xml += DATA_TAG;

    int s = int(_value.asArray->size());
    for (int i=0; i<s; ++i)
       xml += _value.asArray->at(i).toXml();

    xml += DATA_ETAG;
    xml += ARRAY_ETAG;
    xml += VALUE_ETAG;
    return xml;
  }


  // Struct
  bool XmlRpcValue::structFromXml(std::string const& valueXml, int* offset)
  {
    _type = TypeStruct;
    _value.asStruct = new ValueStruct;

    while (XmlRpcUtil::nextTagIs(MEMBER_TAG, valueXml, offset)) {
      // name
      const std::string name = XmlRpcUtil::parseTag(NAME_TAG, valueXml, offset);
      // value
      XmlRpcValue val(valueXml, offset);
      if ( ! val.valid()) {
        invalidate();
        return false;
      }
      const std::pair<const std::string, XmlRpcValue> p(name, val);
      _value.asStruct->insert(p);

      (void) XmlRpcUtil::nextTagIs(MEMBER_ETAG, valueXml, offset);
    }
    return true;
  }


  // In general, its preferable to generate the xml of each element
  // as it is needed rather than glomming up one big string.
  std::string XmlRpcValue::structToXml() const
  {
    std::string xml = VALUE_TAG;
    xml += STRUCT_TAG;

    ValueStruct::const_iterator it;
    for (it=_value.asStruct->begin(); it!=_value.asStruct->end(); ++it) {
      xml += MEMBER_TAG;
      xml += NAME_TAG;
      xml += XmlRpcUtil::xmlEncode(it->first);
      xml += NAME_ETAG;
      xml += it->second.toXml();
      xml += MEMBER_ETAG;
    }

    xml += STRUCT_ETAG;
    xml += VALUE_ETAG;
    return xml;
  }



  // Write the value without xml encoding it
  std::ostream& XmlRpcValue::write(std::ostream& os) const {
    switch (_type) {
      default:           break;
      case TypeBoolean:  os << _value.asBool; break;
      case TypeInt:      os << _value.asInt; break;
      case TypeDouble:   os << _value.asDouble; break;
      case TypeString:   os << *_value.asString; break;
      case TypeDateTime:
        {
          struct tm* t = _value.asTime;
          char buf[20];
          snprintf(buf, sizeof(buf)-1, "%4d%02d%02dT%02d:%02d:%02d", 
            t->tm_year,t->tm_mon,t->tm_mday,t->tm_hour,t->tm_min,t->tm_sec);
          buf[sizeof(buf)-1] = 0;
          os << buf;
          break;
        }
      case TypeBase64:
        {
          int iostatus = 0;
          std::ostreambuf_iterator<char> out(os);
          base64<char> encoder;
          encoder.put(_value.asBinary->begin(), _value.asBinary->end(), out, iostatus, base64<>::crlf());
          break;
        }
      case TypeArray:
        {
          int s = int(_value.asArray->size());
          os << '{';
          for (int i=0; i<s; ++i)
          {
            if (i > 0) os << ',';
            _value.asArray->at(i).write(os);
          }
          os << '}';
          break;
        }
      case TypeStruct:
        {
          os << '[';
          ValueStruct::const_iterator it;
          for (it=_value.asStruct->begin(); it!=_value.asStruct->end(); ++it)
          {
            if (it!=_value.asStruct->begin()) os << ',';
            os << it->first << ':';
            it->second.write(os);
          }
          os << ']';
          break;
        }
      
    }
    
    return os;
  }

} // namespace XmlRpc


// ostream
std::ostream& operator<<(std::ostream& os, XmlRpc::XmlRpcValue& v) 
{ 
  // If you want to output in xml format:
  //return os << v.toXml(); 
  return v.write(os);
}

Test.c
#include <iostream>
#include "src/XmlRpc.h"

using namespace XmlRpc;

int main(int argc, char* argv[])
{

   XmlRpcClient c("xmlrpc.secondlife.com", 80, "/cgi-bin/xmlrpc.cgi");
   
   XmlRpcValue testLSL,result;   

   testLSL["Channel"] = "83af2b8d-80fa-1db6-b35a-b9c0c2dc8670";
   testLSL["IntValue"] = 50;
   testLSL["StringValue"] = "Hello World!";
      
   if (c.execute("llRemoteData", testLSL, result)) 
     {
 std::cout << "Returned:\n";
 std::cout << "\t" << result["IntValue"] << "\n\t" << result["StringValue"] << "\n\n";
     }
   else 
     {
 std::cout << "Error calling 'llRemoteData'\n\n";
     }
   
   return 0;
}




C++ Example 2


This C++ example uses the KDE 3.x libraries (Linux) and reads the XML data from a file.

test.h
#include <kio/job.h>

class Test : public QObject
{
	Q_OBJECT

	public:
		Test();

	protected slots:
		void requestData
			(KIO::Job *job, const QByteArray &data);
		void requestResult
			(KIO::Job *job);
};

test.cpp
#include "test.moc"

#include <kapp.h>
#include <kaboutdata.h>
#include <kcmdlineargs.h>

#include <kfile.h>
#include <stream.h>

int main(int argc, char **argv)
{
	KAboutData about("test", "Test", "0.1",
		"A test of communication with SL", KAboutData::License_GPL,
	       	"Copyright (c) 2007 LSL wiki");
	KCmdLineArgs::init(argc, argv, &about);
	KApplication application(false, false);

	Test *test = new Test();

	return application.exec();
}

Test::Test()
	: QObject()
{
	KIO::SimpleJob *job;
	KURL address("http://xmlrpc.secondlife.com/cgi-bin/xmlrpc.cgi");
	QFile testFile("test.xml");
	QByteArray toSend;

	if (!testFile.open(IO_ReadOnly))
	{
		cerr << "Failed to open XML file";
		return;
	}
	toSend = testFile.readAll();
	testFile.close();

	job = KIO::http_post(address, toSend, false);
	job->addMetaData("accept", "text/xml, */*");
	job->addMetaData("content-type", "Content-type: application/x-www-form-urlencoded");

	connect(job,
		SIGNAL(data(KIO::Job *, const QByteArray &)),
		this,
		SLOT(requestData(KIO::Job *, const QByteArray &)));
	connect(job,
		SIGNAL(result(KIO::Job *)),
		this,
		SLOT(requestResult(KIO::Job *)));
}

void Test::requestData(KIO::Job *job, const QByteArray &data)
{
	cout << data;
}

void Test::requestResult(KIO::Job *job)
{
	if (job->error())
		cerr << "Failure";
       	else cout << "Transfer succeeded";
}

test.moc

Is generated automatically using Qt's "moc" utility.




Java


This Java example uses the XML-RPC implementation available from the Apache Web Services Project. This example uses an outdated version of the library... does anyone want to fix it? -Fixed using v3.0 of apache. Revised code below. DeleriumHannibal

import java.net.URL;
import java.util.Hashtable;
import java.util.Vector;
import org.apache.xmlrpc.client.XmlRpcClient;
import org.apache.xmlrpc.client.XmlRpcClientConfigImpl;

public class RpcTest {
    
    public static void main(String[] args) {
        /*
         * Put the arguments into an XML-RPC struct, represented by
         * a Java Hashtable.
         */
        Hashtable s = new Hashtable();
        s.put("Channel", "5b90c3ad-a641-fc2c-55e1-dfcc3eefc7cd");
        s.put("IntValue", new Integer(17));
        s.put("StringValue", "Hello, Alexander!");
        
        /*
         * Argument list for the call is a vector containing the struct.
         */
        Vector v = new Vector();
        v.add(s);
        
        try {
            XmlRpcClientConfigImpl config = new XmlRpcClientConfigImpl();
            config.setServerURL(new URL("http://xmlrpc.secondlife.com:80/cgi-bin/xmlrpc.cgi"));
            XmlRpcClient client = new XmlRpcClient();
            client.setConfig(config);
            Object result = client.execute("llRemoteData", v);
            if (result != null)
                System.out.println("Result class: " + result.getClass().getName());
        } catch(Exception e) {
            System.out.println("Failed: " + e);
        }
    }
    
}



JavaScript


This JavaScript example uses the JavaScript O Lait http://jsolait.net/index.xhtml library by Jan-Klaas Kollhof. However you should note that the default settings on most browsers do not allow XML-RPC to external websites.

<script type="text/javascript" src="http://jsolait.net/examples/xmlrpc/jsolait/init.js"></script>  <!--- You can replace these with local copies (download from http://jsolait.net/doc/index.xhtml) --->
<script type="text/javascript" src="http://jsolait.net/examples/xmlrpc/jsolait/lib/urllib.js"></script>
<script type="text/javascript" src="http://jsolait.net/examples/xmlrpc/jsolait/lib/xml.js"></script>
<script type="text/javascript" src="http://jsolait.net/examples/xmlrpc/jsolait/lib/xmlrpc.js"></script>
<script type="text/javascript" >
var xmlrpc=null;
try{
    var xmlrpc = importModule("xmlrpc");
}catch(e){
    reportException(e);
    throw "importing of xmlrpc module failed.";
}

function send_rpc(){
    var addr = "http://xmlrpc.secondlife.com/cgi-bin/xmlrpc.cgi";

    var sChannel = "0d58c21c-b56f-57df-745f-9ccd0e06df49";  // Add your ChannelID and arguments (can be pulled from textboxes)
    var iValue = 17;
    var sString = "Hello, Alexander!";
    var evalStr = {"Channel" : sChannel, "IntValue" : iValue, "StringValue" : sString};
    
    try{
        var service = new xmlrpc.ServiceProxy(addr);
        var rslt = service.llRemoteData(evalStr);  // Result object
		
        alert(rslt["StringValue"]);  // Returns String Value
		alert(rslt["IntValue"]);  // Returns Int Value
    }catch(e){
        var em;
        if(e.toTraceString){
            em=e.toTraceString();
        }else{
            em = e.message;
        }
        alert("Error trace: \n\n" + em);
    }
    return false;
}
</script>



Perl

Here's an example in Perl. It uses the RPC::XML module that is available from CPAN.
The values for $key, $ival and $sval need to be valid of course.
require RPC::XML;
require RPC::XML::Client;

my $client = RPC::XML::Client->new('http://xmlrpc.secondlife.com:80/cgi-bin/xmlrpc.cgi');

my $request = RPC::XML::request->new('llRemoteData', RPC::XML::struct->new(
   'Channel'   => RPC::XML::string->new($key),
   'IntValue' => RPC::XML::int->new($ival),
   'StringValue' => RPC::XML::string->new($sval)
   )
);

my $response = $client->simple_request($request);
if (!$response) {
   print $RPC::XML::ERROR, "\n";
} else {
   print $response->{StringValue}, "\n";
   print $response->{IntValue}, "\n";
}



PHP Example 1

Here's an implementation in PHP, using PHP's XML-RPC library. Note that you may need to compile it into your PHP build. Users of the PHP Windows binaries just need to add extension=php_xmlrpc.dll into their php.ini.
<?php
 
function llRemoteData($channel$intvalue$stringvalue) {
  
$host "xmlrpc.secondlife.com";
  
$port 80;
  
$uri "/cgi-bin/xmlrpc.cgi";
  
$request xmlrpc_encode_request('llRemoteData',
   array( 
'Channel' => $channel,
    
'IntValue' => $intvalue,
    
'StringValue' => $stringvalue));
  
$fp fsockopen($host$port$errno$errstr);
  
$query "POST " $uri " HTTP/1.0\n" .
    
"User_Agent: PHP XML-RPC Interface\n" .
    
"Host: " $host "\n" .
    
"Content-Type: text/xml\n" .
    
"Content-Length: " strlen($request) . "\n\n" .
    
$request "\n";
 
  if (!
fputs($fp$querystrlen($query)))
   return 
NULL// some sort of write error occured
 
  
$xmlresp "";
 
//I replaced some code that was here but did not work. This should work just as well, in less code and quicker ;p
//read the maximum amount (if you have more bytes than 8192, this method will not work)
 
$response fread($fp8192);
//grab the XML
 
$xmlresp = (substr($responsestrpos($response"\r\n\r\n")+4));
 
  
fclose($fp);
  if (
$xmlresp == "")
   return 
NULL;
  else
   return 
xmlrpc_decode($xmlresp);
 }
?>



PHP Example 2

Here is a way to send RPC without the need of special includes
<?php
  
function postToHost($host$path$data_to_send) {
    
$fp fsockopen($host80);
    
fputs($fp"POST $path HTTP/1.1\r\n");
    
fputs($fp"Host: $host\r\n");
    
fputs($fp"Content-type: application/x-www-form-urlencoded\r\n");
    
fputs($fp"Content-length: "strlen($data_to_send) ."\r\n");
    
fputs($fp"Connection: close\r\n\r\n");
    
fputs($fp$data_to_send);
    
$res "";
    while(!
feof($fp)) {
        
$res .= fgets($fp128);
    }
    
fclose($fp);
    return 
substr($resstrpos($res"\r\n\r\n"));;
  }
  
  function 
parseResponse($response) {
    
$result = array();
    if (
preg_match_all('#<name>(.+)</name><value><(string|int)>(.*)</\2></value>#U'$response$regsPREG_SET_ORDER)) {
      foreach(
$regs as $key=>$val) {
        
$result[$val[1]] = $val[3];
      }
    }
    return 
$result;
  }
  
  function 
sendRequest($channel$intValue$stringValue) {
    
$channel htmlspecialchars($channel);
    
$int = (int)$intValue;
    
$string htmlspecialchars($stringValue);
    
    
$data '<?xml version="1.0"?>';
    
$data .= '<methodCall>';
    
$data .= '<methodName>llRemoteData</methodName>';
    
$data .= '<params><param><value><struct>';
    
$data .= '<member><name>Channel</name><value><string>'.$channel.'</string></value></member>';
    
$data .= '<member><name>IntValue</name><value><int>'.$int.'</int></value></member>';
    
$data .= '<member><name>StringValue</name><value><string>'.$string.'</string></value></member>';
    
$data .= '</struct></value></param></params></methodCall>';

    return 
parseResponse(postToHost("xmlrpc.secondlife.com","/cgi-bin/xmlrpc.cgi"$data));
  }
?>



Python Example 1

Client example in python using xmlrpclib (included in Python 2.2+):
#!/usr/local/bin/python

from xmlrpclib import ServerProxy;
import sys;

def llRemoteData(Channel, Int, String):
        client = ServerProxy("http://xmlrpc.secondlife.com/cgi-bin/xmlrpc.cgi");
        return client.llRemoteData({"Channel" : Channel, "IntValue" : Int, "StringValue" : String});


reply = llRemoteData("9307b83e-0739-63d5-86a5-f510aded12f4", 0, "Hello from " + sys.platform);

for name, value in reply.iteritems():
        print name, value;



Python Example 2

Another python example using the python-xmlrpc module which comes as a nice debian package:
#!/usr/bin/python
import xmlrpc
client = xmlrpc.client("xmlrpc.secondlife.com", 80, "/cgi-bin/xmlrpc.cgi")
print client.execute("llRemoteData", [{"Channel": "2ac9fac6-6194-8e2a-2415-06257dea4a72", "IntValue": 0, "StringValue": "yourmessage"}])



Python Example 3

Another python example using twisted:
from twisted.web.xmlrpc import Proxy
from twisted.internet import reactor

def printValue(value):
    print repr(value)
    reactor.stop()

def printError(error):
    print 'error', error
    reactor.stop()

proxy = Proxy('http://xmlrpc.secondlife.com/cgi-bin/xmlrpc.cgi')
proxy.callRemote('llRemoteData', {"Channel": "a9c9b2e5-2b91-3e3e-ef98-a26b83d21fcd", "IntValue": 0, "StringValue": "yourmessage"}).addCallbacks(printValue, printError)
reactor.run()




Ruby

Here is a Ruby example using xmlrpc4r:
#!/usr/bin/ruby

require "xmlrpc/client"

server = XMLRPC::Client.new("xmlrpc.secondlife.com","/cgi-bin/xmlrpc.cgi")

begin
        result = server.call("llRemoteData", {
                "Channel"     => channel,
                "StringValue" => sdata,
                "IntValue"    => idata
        })

        puts "Channel:     #{result['Channel']}"
        puts "StringValue: #{result['StringValue']}"
        puts "IntValue:    #{result['IntValue']}"

rescue XMLRPC::FaultException => e
        puts "Error: #{e.faultCode} (#{e.faultString})"
end


XMLRPC / XMLRPCDiscussion Jasa SEO Murah Jasa SEO Jasa Google Adwords Jasa Adwords Google Adwords Sepatu Safety Sepatu Futsal Cheapes Hostgator Coupon Link Booking Televisori offerte Notebook Offerte Govr Edo Ziedo Portatile Apple RDAnet Lorks Karikatur Bisnis Modal Kecil Bisnis UKM Berita Terbaru Iklan Baris Jasa SEO Murah SEO Indonesia Konsultan SEO SEO Belajar SEO Penumbuh Rambut Kursus SEO Jam Tangan Casio Grosir Baju Bisnis Online Kerupuk Kulit Social Bookmark Kumpulan Puisi WBC Wonogiri Penumbuh Rambut Jam Tangan Murah Jam Tangan Murah Jam Tangan Casio Penumbuh Rambut Kerupuk Kulit Alat Kantor Laku.com Belanja Online Grosir Eceran Murah dan Aman Jasa SEO Model Jilbab Fine Tableware Permanent Hair Removal island investment development professional makeup artist bali private villa sewa mobil jakarta murah Jual rumah Jakarta Contact Lens Technology
There are 4 comments on this page. [Display comments/form]