/*
* A python implementation of the xmlrpc spec from www.xmlrpc.com
*
* Copyright (C) 2001, Shilad Sen, Sourcelight Technologies, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
*
* The author can be reached at:
*
* shilad.sen@sourcelight.com
*
* Shilad Sen
* Sourcelight Technologies, Inc.
* 906 University Place, Suite B-211
* Evanston, IL 60201
*
*/
#include <assert.h>
#include "xmlrpc.h"
#define and &&
#define or ||
#define not !
#define unless(a) if (!(a))
#define TRUE (0==0)
#define FALSE (0!=0)
#define bool int
#define uint unsigned int
#define uchar unsigned char
#define ulong unsigned long
#define ushort unsigned short
static PyObject *logFileObj = NULL;
static PyObject *pySetLogLevel(PyObject *self, PyObject *args);
static PyObject *pySetLogger(PyObject *self, PyObject *args);
static PyObject *getDateFormat(PyObject *self, PyObject *args);
static PyObject *setDateFormat(PyObject *self, PyObject *args);
static PyObject *makeXmlrpcBool(PyObject *self, PyObject *args);
static PyObject *makeXmlrpcBase64(PyObject *self, PyObject *args);
static PyObject *makeXmlrpcDate(PyObject *self, PyObject *args);
static PyObject *makeXmlrpcClient(PyObject *self, PyObject *args);
static PyObject *makeXmlrpcClientFromServe(
PyObject *self,
PyObject *args
);
static PyObject *makeXmlrpcServer(PyObject *self, PyObject *args);
static PyObject *makeXmlrpcSource(PyObject *self, PyObject *args);
static PyObject *rpcEncode(PyObject *self, PyObject *args);
static PyObject *rpcDecode(PyObject *self, PyObject *args);
static PyObject *rpcBuildCall(PyObject *self, PyObject *args);
static PyObject *rpcBuildRequest(PyObject *self, PyObject *args);
static PyObject *rpcBuildResponse(PyObject *self, PyObject *args);
static PyObject *rpcBuildFault(PyObject *self, PyObject *args);
static PyObject *rpcParseResponse(PyObject *self, PyObject *args);
static PyObject *rpcParseCall(PyObject *self, PyObject *args);
static PyObject *rpcParseRequest(PyObject *self, PyObject *args);
static void *setPyErr(char *error);
static int insint(PyObject *d, char *name, int value);
static int insstr(PyObject *d, char *name, char *value);
/*
* Module function map
*/
static PyMethodDef rpcModuleMethods[] = {
/* client-server */
{ "client", (PyCFunction)makeXmlrpcClient, 1, },
{ "clientFromServer", (PyCFunction)makeXmlrpcClientFromServe, 1, },
{ "server", (PyCFunction)makeXmlrpcServer, 1, },
/* encoders */
{ "boolean", (PyCFunction)makeXmlrpcBool, 1, },
{ "base64", (PyCFunction)makeXmlrpcBase64, 1, },
{ "dateTime", (PyCFunction)makeXmlrpcDate, 1, },
{ "source", (PyCFunction)makeXmlrpcSource, 1, },
{ "encode", (PyCFunction)rpcEncode, 1, },
{ "buildCall", (PyCFunction)rpcBuildCall, 1, },
{ "buildRequest", (PyCFunction)rpcBuildRequest, 1, },
{ "buildResponse", (PyCFunction)rpcBuildResponse, 1, },
{ "buildFault", (PyCFunction)rpcBuildFault, 1, },
/* parsers for data */
{ "decode", (PyCFunction)rpcDecode, 1, },
{ "parseCall", (PyCFunction)rpcParseCall, 1, },
{ "parseRequest", (PyCFunction)rpcParseRequest, 1, },
{ "parseResponse", (PyCFunction)rpcParseResponse, 1, },
/* misc functions */
{ "setLogLevel", (PyCFunction)pySetLogLevel, 1, },
{ "setLogger", (PyCFunction)pySetLogger, 1, },
{ "getDateFormat", (PyCFunction)getDateFormat, 1, },
{ "setDateFormat", (PyCFunction)setDateFormat, 1, },
{ NULL, NULL, 0, },
};
/*
* module procedure: set the log level
*/
static PyObject *
pySetLogLevel(PyObject *self, PyObject *args)
{
int level;
unless (PyArg_ParseTuple(args, "i", &level))
return NULL;
setLogLevel(level);
Py_INCREF(Py_None);
return Py_None;
}
/*
* module procedure: set the logger file
*/
static PyObject *
pySetLogger(PyObject *self, PyObject *args)
{
PyObject *object = NULL;
FILE *file = NULL;
unless (PyArg_ParseTuple(args, "O!", &PyFile_Type, &object))
return NULL;
assert(object != NULL);
assert(PyFile_Check(object));
if (logFileObj != NULL) {
Py_DECREF(logFileObj);
}
logFileObj = object;
Py_INCREF(logFileObj);
file = PyFile_AsFile(object);
setLogger(file);
Py_INCREF(Py_None);
return Py_None;
}
/*
* module procedure: create a base64 object
*/
static PyObject *
setDateFormat(PyObject *self, PyObject *args)
{
int i;
unless (PyArg_ParseTuple(args, "i", &i))
return (NULL);
if ((i != XMLRPC_DATE_FORMAT_US)
and (i != XMLRPC_DATE_FORMAT_EUROPE))
return setPyErr("date format must be DATE_FORMAT_US or DATE_FORMAT_EUROPE");
rpcDateFormat = i;
Py_INCREF(Py_None);
return (Py_None);
}
/*
* module procedure: create a base64 object
*/
static PyObject *
getDateFormat(PyObject *self, PyObject *args)
{
unless (PyArg_ParseTuple(args, ""))
return (NULL);
return (PyInt_FromLong((long)rpcDateFormat));
}
/*
* module procedure: create a boolean object
*/
static PyObject *
makeXmlrpcBool(PyObject *self, PyObject *args)
{
int value;
unless (PyArg_ParseTuple(args, "i", &value))
return NULL;
return rpcBoolNew(value);
}
/*
* module procedure: create a base64 object
*/
static PyObject *
makeXmlrpcBase64(PyObject *self, PyObject *args)
{
PyObject *str;
unless (PyArg_ParseTuple(args, "S", &str))
return (NULL);
return (rpcBase64New(str));
}
/*
* module procedure: create a date object
*/
static PyObject *
makeXmlrpcDate(PyObject *self, PyObject *args)
{
PyObject *tmp;
int i;
unless (PyTuple_Check(args)) {
PyErr_SetString(rpcError, "dateTime expects a 6-int tuple");
return (NULL);
}
unless (PyTuple_Size(args) == 6) {
PyErr_SetString(rpcError, "dateTime expects a 6-int tuple");
return (NULL);
}
for (i = 0; i < 6; ++i) {
tmp = PyTuple_GET_ITEM(args, i);
unless (PyInt_Check(tmp)) {
PyErr_SetString(rpcError, "tuple must be ints");
return (NULL);
}
}
return (rpcDateNew(args));
}
/*
* module procedure: create a boolean object
*/
static PyObject *
makeXmlrpcClient(PyObject *self, PyObject *args)
{
char *host,
*url;
int port;
unless (PyArg_ParseTuple(args, "sis", &host, &port, &url))
return NULL;
return (PyObject *)rpcClientNew(host, port, url);
}
/*
* module procedure: create a boolean object
*/
static PyObject *
makeXmlrpcClientFromServe(PyObject *self, PyObject *args)
{
rpcServer *servp;
char *host,
*url;
int port;
unless (PyArg_ParseTuple(args, "sisO!",
&host, &port, &url, &rpcServerType, &servp))
return NULL;
return (PyObject *)rpcClientNewFromServer(host, port, url, servp);
}
/*
* module procedure: create a server object
*/
static PyObject *
makeXmlrpcServer(PyObject *self, PyObject *args)
{
unless (PyArg_ParseTuple(args, ""))
return NULL;
return (PyObject *)rpcServerNew();
}
/*
* module procedure: create a source object
*/
static PyObject *
makeXmlrpcSource(PyObject *self, PyObject *args)
{
int fd;
unless (PyArg_ParseTuple(args, "i", &fd))
return NULL;
return (PyObject *)rpcSourceNew(fd);
}
/*
* module procedure: encode an object in xml
*/
static PyObject *
rpcEncode(PyObject *self, PyObject *args)
{
PyObject *value;
unless (PyArg_ParseTuple(args, "O", &value))
return NULL;
return xmlEncode(value);
}
/*
* module procedure: encode an object in xml
*/
static PyObject *
rpcDecode(PyObject *self, PyObject *args)
{
PyObject *sp;
unless (PyArg_ParseTuple(args, "S", &sp))
return NULL;
return xmlDecode(sp);
}
/*
* module procedure: encode a request and return the xml string
*/
static PyObject *
rpcBuildCall(PyObject *self, PyObject *args)
{
char *method;
PyObject *params;
unless (PyArg_ParseTuple(args, "sO", &method, ¶ms))
return NULL;
unless (PySequence_Check(params))
return setPyErr("build request params must be a sequence");
return buildCall(method, params);
}
/*
* module procedure: encode an object in xml
*/
static PyObject *
rpcBuildRequest(PyObject *self, PyObject *args)
{
char *method,
*url;
PyObject *params,
*addInfo;
unless (PyArg_ParseTuple(args, "ssOO",
&url, &method, ¶ms, &addInfo))
return NULL;
unless (PyDict_Check(addInfo))
return setPyErr("additional info must be a dictonary");
unless (PySequence_Check(params))
return setPyErr("build request params must be a sequence");
return buildRequest(url, method, params, addInfo);
}
/*
* module procedure: encode an object in xml
*/
static PyObject *
rpcBuildResponse(PyObject *self, PyObject *args)
{
PyObject *result,
*addInfo;
unless (PyArg_ParseTuple(args, "OO", &result, &addInfo))
return NULL;
unless (PyDict_Check(addInfo))
return setPyErr("additional info must be a dictonary");
return buildResponse(result, addInfo);
}
/*
* module procedure: encode an object in xml
*/
static PyObject *
rpcBuildFault(PyObject *self, PyObject *args)
{
PyObject *addInfo;
int errCode;
char *errStr;
unless (PyArg_ParseTuple(args, "isO", &errCode, &errStr, &addInfo))
return NULL;
unless (PyDict_Check(addInfo))
return setPyErr("additional info must be a dictonary");
return buildFault(errCode, errStr, addInfo);
}
/*
* module procedure: encode an object in xml
*/
static PyObject *
rpcParseCall(PyObject *self, PyObject *args)
{
PyObject *request;
unless (PyArg_ParseTuple(args, "O", &request))
return NULL;
unless (PyString_Check(request))
return setPyErr("request must be a string");
return parseCall(request);
}
/*
* module procedure: encode an object in xml
*/
static PyObject *
rpcParseResponse(PyObject *self, PyObject *args)
{
PyObject *response;
unless (PyArg_ParseTuple(args, "O", &response))
return NULL;
unless (PyString_Check(response))
return setPyErr("response must be a string");
return parseResponse(response);
}
/*
* module procedure: encode an object in xml
*/
static PyObject *
rpcParseRequest(PyObject *self, PyObject *args)
{
PyObject *request;
unless (PyArg_ParseTuple(args, "O", &request))
return NULL;
unless (PyString_Check(request))
return setPyErr("request must be a string");
return parseRequest(request);
}
/*
* module initialization done at load time
*/
void
init_xmlrpc(void) {
PyObject *m, *d;
xmlrpcInit();
#ifdef MS_WINDOWS
unless (rpcNTinit())
return;
#endif
m = Py_InitModule("_xmlrpc", rpcModuleMethods);
d = PyModule_GetDict(m);
PyDict_SetItemString(d, "error", rpcError);
PyDict_SetItemString(d, "fault", rpcFault);
PyDict_SetItemString(d, "postpone", rpcPostpone);
unless ((insint(d, "ACT_INPUT", ACT_INPUT))
and (insint(d, "ACT_OUTPUT", ACT_OUTPUT))
and (insint(d, "ACT_EXCEPT", ACT_EXCEPT))
and (insint(d, "ONERR_TYPE_C", ONERR_TYPE_C))
and (insint(d, "ONERR_TYPE_PY", ONERR_TYPE_PY))
and (insint(d, "ONERR_TYPE_DEF", ONERR_TYPE_DEF))
and (insint(d, "ONERR_KEEP_DEF", ONERR_KEEP_DEF))
and (insint(d, "ONERR_KEEP_SRC", ONERR_KEEP_SRC))
and (insint(d, "ONERR_KEEP_WORK", ONERR_KEEP_WORK))
and (insint(d, "DATE_FORMAT_US", XMLRPC_DATE_FORMAT_US))
and (insint(d, "DATE_FORMAT_EUROPE", XMLRPC_DATE_FORMAT_EUROPE))
and (insstr(d, "VERSION", XMLRPC_VER))
and (insstr(d, "LIBRARY", XMLRPC_LIB_STR))) {
fprintf(rpcLogger, "weird shit happened in module loading\n");
return;
}
}
/*
* Convenience routine to export an integer value.
*/
static int
insint(PyObject *d, char *name, int value)
{
PyObject *v = PyInt_FromLong((long) value);
if (v == NULL)
return FALSE;
if (PyDict_SetItemString(d, name, v) == 0) {
PyErr_Clear();
Py_DECREF(v);
return TRUE;
}
Py_DECREF(v);
return FALSE;
}
/*
* Convenience routine to export a string value.
*/
static int
insstr(PyObject *d, char *name, char *value)
{
PyObject *v = PyString_FromString(value);
if (v == NULL)
return FALSE;
if (PyDict_SetItemString(d, name, v) == 0) {
Py_DECREF(v);
PyErr_Clear();
return TRUE;
}
Py_DECREF(v);
return FALSE;
}
/*
* Set the python error and return NULL
*/
static void *
setPyErr(char *error)
{
PyErr_SetString(rpcError, error);
return NULL;
}
syntax highlighted by Code2HTML, v. 0.9.1