/**********************************************************************************
* nWordPress is an automated migration of WordPress 2.5.1 performed by Numiton.
*
* copyright : (C) 2008 Numiton - www.numiton.com
* email : numiton@users.sourceforge.net
*
* $Id: IXR_Server.java,v 1.4 2008/10/14 13:15:48 numiton Exp $
*
**********************************************************************************/
/**********************************************************************************
*
* 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 2 of the License, or
* (at your option) any later version.
*
**********************************************************************************/
/***************************************************************************
*
* 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 2 of the License, or
* (at your option) any later version.
*
***************************************************************************/
package org.numiton.nwp.wp_includes;
import static com.numiton.VarHandling.*;
import java.io.Serializable;
import java.util.Map;
import org.apache.log4j.Logger;
import org.numiton.nwp.GlobalConsts;
import org.numiton.nwp.GlobalVars;
import com.numiton.*;
import com.numiton.System;
import com.numiton.array.Array;
import com.numiton.array.ArrayEntry;
import com.numiton.generic.*;
import com.numiton.string.Strings;
public class IXR_Server implements ContextCarrierInterface, Serializable, Cloneable {
protected static final Logger LOG = Logger.getLogger(IXR_Server.class.getName());
public GlobalConsts gConsts;
public GlobalVars gVars;
public Object data;
public Array<Object> callbacks = new Array<Object>();
public IXR_Message message;
public Array<Object> capabilities = new Array<Object>();
public IXR_Server(GlobalVars javaGlobalVariables, GlobalConsts javaGlobalConstants, Array<Object> callbacks) {
this(javaGlobalVariables, javaGlobalConstants, callbacks, "");
}
public IXR_Server(GlobalVars javaGlobalVariables, GlobalConsts javaGlobalConstants, Array<Object> callbacks, String data) {
setContext(javaGlobalVariables, javaGlobalConstants);
this.setCapabilities();
if (booleanval(callbacks)) {
this.callbacks = callbacks;
}
this.setCallbacks();
this.serve(data);
}
// Added by Numiton
public IXR_Server(GlobalVars javaGlobalVariables, GlobalConsts javaGlobalConstants) {
this(javaGlobalVariables, javaGlobalConstants, null, null);
}
public void serve(String data) {
Object result = null;
IXR_Value r = null;
String resultxml = null;
String xml = null;
if (!booleanval(data)) {
if (!booleanval(gVars.webEnv.HTTP_RAW_POST_DATA)) {
System.exit("XML-RPC server accepts POST requests only.");
}
data = gVars.webEnv.HTTP_RAW_POST_DATA;
}
this.message = new IXR_Message(gVars, gConsts, data);
if (!this.message.parse()) {
this.error(-32700, "parse error. not well formed");
}
if (!equal(this.message.messageType, "methodCall")) {
this.error(-32600, "server error. invalid xml-rpc. not conforming to spec. Request must be a methodCall");
}
result = this.call(this.message.methodName, this.message.params);
// Is the result an error?
if (ClassHandling.is_a(result, "IXR_Error")) {
this.error(result);
}
// Encode the result
r = new IXR_Value(gVars, gConsts, result);
resultxml = r.getXml();
// Create the XML
xml = "<methodResponse>\n <params>\n <param>\n <value>\n " + resultxml + "\n </value>\n </param>\n </params>\n</methodResponse>\n\n";
// Send it
this.output(xml);
}
public Object call(String methodname, Object args) {
Object method = null;
/* Do not change type */
Object result = null;
if (!this.hasMethod(methodname)) {
return new IXR_Error(gVars, gConsts, -32601, "server error. requested method " + methodname + " does not exist.");
}
method = this.callbacks.getValue(methodname);
// Perform the callback and send the response
if (equal(Array.count(args), 1)) {
// If only one paramater just send that instead of the whole array
args = ((Array) args).getValue(0);
}
// Are we dealing with a function or a method?
if (equal(Strings.substr(strval(method), 0, 5), "this:")) {
// It's a class method - check it exists
method = Strings.substr(strval(method), 5);
if (!ClassHandling.method_exists(this, strval(method))) {
return new IXR_Error(gVars, gConsts, -32601, "server error. requested class method \"" + method + "\" does not exist.");
}
// Modified by Numiton
// Call the method
result = FunctionHandling.call_user_func(new Callback(strval(method), this), args);
} else {
// It's a function - does it exist?
if (is_array(method)) {
if (!ClassHandling.method_exists(strval(((Array) method).getValue(0)), strval(((Array) method).getValue(1)))) {
return new IXR_Error(gVars, gConsts, -32601, "server error. requested object method \"" + strval(((Array) method).getValue(1)) + "\" does not exist.");
}
} else if (!VarHandling.is_callable(new Callback(strval(method), this))) {
return new IXR_Error(gVars, gConsts, -32601, "server error. requested function \"" + method + "\" does not exist.");
}
// Call the function
result = FunctionHandling.call_user_func(new Callback(strval(method), this), args);
}
return result;
}
public void error(Object error) {
error(error, "");
}
public void error(Object error, /* Do not change type */String message) {
// Accepts either an error object or an error code and message
if (booleanval(message) && !is_object(error)) {
error = new IXR_Error(gVars, gConsts, intval(error), message);
}
this.output(((IXR_Error) error).getXml());
}
public void output(String xml) {
int length = 0;
xml = "<?xml version=\"1.0\"?>" + "\n" + xml;
length = Strings.strlen(xml);
Network.header(gVars.webEnv, "Connection: close");
Network.header(gVars.webEnv, "Content-Length: " + strval(length));
Network.header(gVars.webEnv, "Content-Type: text/xml");
Network.header(gVars.webEnv, "Date: " + DateTime.date("r"));
echo(gVars.webEnv, xml);
System.exit();
}
public boolean hasMethod(String method) {
return Array.in_array(method, Array.array_keys(this.callbacks));
}
public void setCapabilities() {
// Initialises capabilities array
this.capabilities = new Array<Object>(
new ArrayEntry<Object>("xmlrpc", new Array<Object>(new ArrayEntry<Object>("specUrl", "http://www.xmlrpc.com/spec"), new ArrayEntry<Object>("specVersion", 1))),
new ArrayEntry<Object>(
"faults_interop",
new Array<Object>(new ArrayEntry<Object>("specUrl", "http://xmlrpc-epi.sourceforge.net/specs/rfc.fault_codes.php"), new ArrayEntry<Object>("specVersion", 20010516))),
new ArrayEntry<Object>("system.multicall",
new Array<Object>(new ArrayEntry<Object>("specUrl", "http://www.xmlrpc.com/discuss/msgReader$1208"), new ArrayEntry<Object>("specVersion", 1))));
}
public Array<Object> getCapabilities(Object args) {
return this.capabilities;
}
public void setCallbacks() {
this.callbacks.putValue("system.getCapabilities", "this:getCapabilities");
this.callbacks.putValue("system.listMethods", "this:listMethods");
this.callbacks.putValue("system.multicall", "this:multiCall");
}
public Array<Object> listMethods(Object args) {
// Returns a list of methods - uses array_reverse to ensure user defined
// methods are listed before server defined methods
return Array.array_reverse(Array.array_keys(this.callbacks));
}
public Array<Object> multiCall(Array<Object> methodcalls) {
Array<Object> _return = new Array<Object>();
Object method = null;
Array<Object> call = new Array<Object>();
Object params = null;
Object result = null;
// See http://www.xmlrpc.com/discuss/msgReader$1208
_return = new Array<Object>();
for (Map.Entry javaEntry406 : methodcalls.entrySet()) {
call = (Array<Object>) javaEntry406.getValue();
method = call.getValue("methodName");
params = call.getValue("params");
if (equal(method, "system.multicall")) {
result = new IXR_Error(gVars, gConsts, -32600, "Recursive calls to system.multicall are forbidden");
} else {
result = this.call(strval(method), params);
}
if (ClassHandling.is_a(result, "IXR_Error")) {
_return.putValue(new Array<Object>(new ArrayEntry<Object>("faultCode", ((IXR_Error) result).code), new ArrayEntry<Object>("faultString", ((IXR_Error) result).message)));
} else {
_return.putValue(new Array<Object>(new ArrayEntry<Object>(result)));
}
}
return _return;
}
public void setContext(GlobalVariablesContainer javaGlobalVariables, GlobalConstantsInterface javaGlobalConstants) {
gConsts = (GlobalConsts) javaGlobalConstants;
gVars = (GlobalVars) javaGlobalVariables;
gVars.gConsts = gConsts;
}
public Object clone() throws CloneNotSupportedException {
return super.clone();
}
public GlobalVariablesContainer getGlobalVars() {
return gVars;
}
}