/**
* @author Ma Bingyao(andot@ujn.edu.cn)
* @copyright CoolCode.CN
* @package JAVA_PHPRPC_CLIENT
* @version 2.1
* @last_update 2006-08-09
* @link http://www.coolcode.cn/?p=205
*
* Example usage:
import java.lang.*;
import org.phprpc.*;
public class SinTest
{
public static void main(String[] args) {
PHPRPCClient rpc = new PHPRPCClient();
rpc.useService("http://localhost:8080/phprpc_2.1/sample/server.jsp", true);
rpc.setEncrypt(2);
System.out.println(rpc.invoke("sin", new Double(args[0])));
}
}
*
*/
package org.phprpc;
import java.lang.*;
import java.io.*;
import java.util.*;
import java.math.*;
import java.net.*;
import org.phprpc.util.*;
public class PHPRPCClient {
private String __uri;
private String __charset;
private String __cookies;
private String __output;
private byte __encrypt;
private PHPRPCError __warning;
private byte[] __key;
private HashMap __proxy = null;
private String __user;
private String __pass;
public PHPRPCClient() {
this.__uri = null;
this.__proxy = null;
this.__encrypt = 0;
this.__user = null;
this.__pass = null;
}
public String getOutput() {
return __output;
}
public byte getEncrypt() {
return __encrypt;
}
public void setEncrypt(int value) {
__encrypt = (byte)value;
}
public PHPRPCError getWarning() {
return __warning;
}
public void setProxy(String host, int port) {
this.__proxy = new HashMap();
this.__proxy.put("host", host);
this.__proxy.put("port", new Integer(port));
}
public void setProxy(String host, int port, String user, String pass) {
this.__proxy = new HashMap();
this.__proxy.put("host", host);
this.__proxy.put("port", new Integer(port));
this.__proxy.put("user", user);
this.__proxy.put("pass", pass);
}
public void setProxy(HashMap proxy) {
this.__proxy = proxy;
}
public void setAuth(String user, String pass) {
this.__user = user;
this.__pass = pass;
}
public boolean useService(String requestUriString) throws IOException, IllegalAccessException {
return useService(requestUriString, false);
}
public boolean useService(String requestUriString, boolean encrypt) throws IOException, IllegalAccessException {
this.__uri = requestUriString;
this.__warning = null;
this.__output = "";
this.__cookies = null;
this.__charset = null;
this.__key = null;
if (encrypt) {
return SwitchKey();
} else {
Socket socket = this.__request("", "GET");
InputStream is = socket.getInputStream();
HashMap header = new HashMap();
this.__getContent(is, header, null);
is.close();
socket.close();
this.__charset = this.__getCharset(header);
return true;
}
}
private String __getCharset(HashMap header) {
if (header.containsKey("Content-Type")) {
String charset = (String)header.get("Content-Type");
if (charset.startsWith("text/plain; charset=")) {
return charset.substring(20);
}
}
return "UTF-8";
}
private String __getCookies(HashMap header) {
if (header.containsKey("Set-Cookie")) {
String cookies = (String)header.get("Set-Cookie");
int pos1, pos2;
pos1 = cookies.indexOf("path=");
if (pos1 > -1) {
pos2 = cookies.indexOf(";", pos1);
if (pos2 == -1) {
pos2 = cookies.length();
} else {
pos2++;
}
cookies = (new StringBuffer(cookies)).delete(pos1, pos2).toString();
}
pos1 = cookies.indexOf("domain=");
if (pos1 > -1) {
pos2 = cookies.indexOf(";", pos1);
if (pos2 == -1) {
pos2 = cookies.length();
} else {
pos2++;
}
cookies = (new StringBuffer(cookies)).delete(pos1, pos2).toString();
}
return cookies;
} else {
return null;
}
}
private Socket __request(String requestString, String method) throws IOException {
URL url = new URL(this.__uri);
String host = url.getHost();
int port = url.getPort();
if (port == -1) {
port = 80;
}
Socket socket;
try {
if (this.__proxy != null) {
socket = new Socket((String)(this.__proxy.get("host")), ((Integer)(this.__proxy.get("port"))).intValue());
} else {
socket = new Socket(host , port);
}
} catch (Exception e) {
return null;
}
String proxy = "";
if (this.__proxy != null) {
proxy = "Proxy-Connection: Keep-Alive\r\n";
if (this.__proxy.containsKey("user") && this.__proxy.containsKey("pass")) {
proxy += "Proxy-Authorization: Basic " +
Base64.encode(((String)(this.__proxy.get("user")) + ":" + (String)(this.__proxy.get("pass"))).getBytes()) +
"\r\n";
}
}
String auth = "";
if (this.__user != null && this.__pass != null) {
auth = "Authorization: Basic " + Base64.encode((this.__user + ":" + this.__pass).getBytes()) + "\r\n";
}
String cookie = "";
if (this.__cookies != null) {
cookie = "Cookie: " + this.__cookies + "\r\n";
}
OutputStream os = socket.getOutputStream();
String httpHead;
if (method.toUpperCase().equals("GET")) {
httpHead = "GET " + url.toString() + "?" + requestString + " HTTP/1.0\r\n" +
"User-Agent: PHPRPC Client/2.1\r\n" +
"Host: " + host + ":" + port + "\r\n" +
proxy + auth + cookie +
"\r\n";
os.write(httpHead.getBytes());
} else {
byte[] content = requestString.getBytes(this.__charset);
httpHead = "POST " + url.toString() + " HTTP/1.0\r\n" +
"User-Agent: PHPRPC Client/2.1\r\n" +
"Host: " + host + ":" + port + "\r\n" +
proxy + auth + cookie +
"Content-Type: application/x-www-form-urlencoded; charset=" + this.__charset + "\r\n" +
"Content-Length: " + content.length + "\r\n" +
"\r\n";
os.write(httpHead.getBytes(this.__charset));
os.write(content);
}
return socket;
}
private void __getContent(InputStream is, HashMap header, HashMap body) throws IOException {
BufferedReader in = new BufferedReader(new InputStreamReader(is, "UTF-8"));
String buf;
while ((buf = in.readLine()) != null) {
if (buf.equals("")) break;
if (buf.startsWith("HTTP/")) {
header.put("Version", buf.substring(5, 8));
header.put("StatusCode", buf.substring(9, 12));
header.put("Status", buf.substring(13));
} else {
int pos = buf.indexOf(": ");
if (pos > -1) {
header.put(buf.substring(0, pos), buf.substring(pos + 2));
}
}
}
if (body == null) return;
while ((buf = in.readLine()) != null) {
int pos = buf.indexOf("=");
if (pos == -1) break;
if (buf.charAt(pos + 1) == '"') {
body.put(buf.substring(0, pos), buf.substring(pos + 2, buf.length() - 2));
} else {
body.put(buf.substring(0, pos), buf.substring(pos + 1, buf.length() - 1));
}
}
}
private boolean SwitchKey() throws IOException, IllegalAccessException {
Socket socket = this.__request("phprpc_encrypt=true", "GET");
InputStream is = socket.getInputStream();
HashMap header = new HashMap();
HashMap body = new HashMap();
this.__getContent(is, header, body);
this.__charset = this.__getCharset(header);
this.__cookies = this.__getCookies(header);
is.close();
socket.close();
if (body.containsKey("phprpc_encrypt")) {
HashMap kp = (HashMap)PHPSerializer.unserialize(Base64.decode((String)(body.get("phprpc_encrypt"))), this.__charset);
BigInteger p = new BigInteger((String)kp.get("p"));
BigInteger g = new BigInteger((String)kp.get("g"));
BigInteger y = new BigInteger((String)kp.get("y"));
BigInteger x = new BigInteger(127, new Random());
this.__key = new byte[16];
byte[] key = y.modPow(x, p).toByteArray();
for (int i = 1, n = Math.min(key.length, 16); i <= n; i++) {
this.__key[16 - i] = key[key.length - i];
}
this.__request("phprpc_encrypt=" + g.modPow(x, p).toString(), "GET").close();
return true;
} else {
this.__warning = new PHPRPCError(2, "PHPRPC Server can't support encrypt");
return false;
}
}
private void setWarning(String errno, String errstr) {
int number = Integer.parseInt(errno);
if (number != 0) {
try {
this.__warning = new PHPRPCError(number, new String(Base64.decode(errstr), this.__charset));
} catch (Exception e) { }
}
}
private void setOutput(String output) {
try {
this.__output = new String(Base64.decode(output), this.__charset);
} catch (Exception e) { }
}
public Object invoke(String function, Object[] args) throws PHPRPCError, IOException, IllegalAccessException {
return this.invoke(function, args, false);
}
public Object invoke(String function, Object[] args, boolean byref) throws PHPRPCError, IOException, IllegalAccessException {
StringBuffer sb = new StringBuffer();
sb.append("phprpc_func=");
sb.append(function);
if (args.length > 0) {
byte[] arguments = PHPSerializer.serialize(args);
if (this.__key != null && this.__encrypt > 0) {
arguments = XXTEA.encrypt(arguments, this.__key);
}
sb.append("&phprpc_args=");
sb.append(URLEncoder.encode(Base64.encode(arguments)));
if (!byref) {
sb.append("&phprpc_ref=false");
}
}
if (this.__key != null) {
sb.append("&phprpc_encrypt=");
sb.append(this.__encrypt);
}
Socket socket = this.__request(sb.toString(), "POST");
InputStream is = socket.getInputStream();
HashMap header = new HashMap();
HashMap body = new HashMap();
this.__getContent(is, header, body);
is.close();
socket.close();
this.__warning = null;
if (body.containsKey("phprpc_result")) {
byte[] result = Base64.decode((String)body.get("phprpc_result"));
byte[] arguments = null;
boolean has_args = body.containsKey("phprpc_args");
if (has_args) {
arguments = Base64.decode((String)body.get("phprpc_args"));
}
this.setWarning((String)body.get("phprpc_errno"), (String)body.get("phprpc_errstr"));
this.setOutput((String)body.get("phprpc_output"));
if ((this.__key != null) && (this.__encrypt > 0)) {
if (this.__encrypt > 1) {
result = XXTEA.decrypt(result, this.__key);
}
if (has_args) {
arguments = XXTEA.decrypt(arguments, this.__key);
}
}
if (has_args) {
Object[] refargs = (Object[])PHPSerializer.unserialize(arguments, (new Object[0]).getClass(), this.__charset);
for (int i = 0; i < args.length; i++) {
args[i] = refargs[i];
}
}
return PHPSerializer.unserialize(result, this.__charset);
} else if (body.containsKey("phprpc_errno")) {
throw new PHPRPCError(Integer.parseInt((String)(body.get("phprpc_errno"))), new String(Base64.decode((String)(body.get("phprpc_errstr")))));
} else {
throw new PHPRPCError(1, "Wrong PHPRPC Server!");
}
}
}