diff --git a/OSJ Forum/src/org/xmlrpc/android/Base64Coder.java b/OSJ Forum/src/org/xmlrpc/android/Base64Coder.java new file mode 100644 index 0000000..f9a4807 --- /dev/null +++ b/OSJ Forum/src/org/xmlrpc/android/Base64Coder.java @@ -0,0 +1,199 @@ +package org.xmlrpc.android; + +/** + * A Base64 Encoder/Decoder. + * + *
+ * This class is used to encode and decode data in Base64 format as described in + * RFC 1521. + * + *
+ * This is "Open Source" software and released under the GNU/LGPL license.
+ * It is provided "as is" without warranty of any kind.
+ * Copyright 2003: Christian d'Heureuse, Inventec Informatik AG, Switzerland.
+ * Home page: www.source-code.biz
+ *
+ *
+ * Version history:
+ * 2003-07-22 Christian d'Heureuse (chdh): Module created.
+ * 2005-08-11 chdh: Lincense changed from GPL to LGPL.
+ * 2006-11-21 chdh:
+ * Method encode(String) renamed to encodeString(String).
+ * Method decode(String) renamed to decodeString(String).
+ * New method encode(byte[],int) added.
+ * New method decode(String) added.
+ */
+
+class Base64Coder {
+
+ // Mapping table from 6-bit nibbles to Base64 characters.
+ private static char[] map1 = new char[64];
+ static {
+ int i = 0;
+ for (char c = 'A'; c <= 'Z'; c++) {
+ map1[i++] = c;
+ }
+ for (char c = 'a'; c <= 'z'; c++) {
+ map1[i++] = c;
+ }
+ for (char c = '0'; c <= '9'; c++) {
+ map1[i++] = c;
+ }
+ map1[i++] = '+';
+ map1[i++] = '/';
+ }
+
+ // Mapping table from Base64 characters to 6-bit nibbles.
+ private static byte[] map2 = new byte[128];
+ static {
+ for (int i = 0; i < map2.length; i++) {
+ map2[i] = -1;
+ }
+ for (int i = 0; i < 64; i++) {
+ map2[map1[i]] = (byte) i;
+ }
+ }
+
+ /**
+ * Encodes a string into Base64 format. No blanks or line breaks are
+ * inserted.
+ *
+ * @param s
+ * a String to be encoded.
+ * @return A String with the Base64 encoded data.
+ */
+ static String encodeString(String s) {
+ return new String(encode(s.getBytes()));
+ }
+
+ /**
+ * Encodes a byte array into Base64 format. No blanks or line breaks are
+ * inserted.
+ *
+ * @param in
+ * an array containing the data bytes to be encoded.
+ * @return A character array with the Base64 encoded data.
+ */
+ static char[] encode(byte[] in) {
+ return encode(in, in.length);
+ }
+
+ /**
+ * Encodes a byte array into Base64 format. No blanks or line breaks are
+ * inserted.
+ *
+ * @param in
+ * an array containing the data bytes to be encoded.
+ * @param iLen
+ * number of bytes to process in in.
+ * @return A character array with the Base64 encoded data.
+ */
+ static char[] encode(byte[] in, int iLen) {
+ int oDataLen = (iLen * 4 + 2) / 3; // output length without padding
+ int oLen = ((iLen + 2) / 3) * 4; // output length including padding
+ char[] out = new char[oLen];
+ int ip = 0;
+ int op = 0;
+ while (ip < iLen) {
+ int i0 = in[ip++] & 0xff;
+ int i1 = ip < iLen ? in[ip++] & 0xff : 0;
+ int i2 = ip < iLen ? in[ip++] & 0xff : 0;
+ int o0 = i0 >>> 2;
+ int o1 = ((i0 & 3) << 4) | (i1 >>> 4);
+ int o2 = ((i1 & 0xf) << 2) | (i2 >>> 6);
+ int o3 = i2 & 0x3F;
+ out[op++] = map1[o0];
+ out[op++] = map1[o1];
+ out[op] = op < oDataLen ? map1[o2] : '=';
+ op++;
+ out[op] = op < oDataLen ? map1[o3] : '=';
+ op++;
+ }
+ return out;
+ }
+
+ /**
+ * Decodes a string from Base64 format.
+ *
+ * @param s
+ * a Base64 String to be decoded.
+ * @return A String containing the decoded data.
+ * @throws IllegalArgumentException
+ * if the input is not valid Base64 encoded data.
+ */
+ static String decodeString(String s) {
+ return new String(decode(s));
+ }
+
+ /**
+ * Decodes a byte array from Base64 format.
+ *
+ * @param s
+ * a Base64 String to be decoded.
+ * @return An array containing the decoded data bytes.
+ * @throws IllegalArgumentException
+ * if the input is not valid Base64 encoded data.
+ */
+ static byte[] decode(String s) {
+ return decode(s.toCharArray());
+ }
+
+ /**
+ * Decodes a byte array from Base64 format. No blanks or line breaks are
+ * allowed within the Base64 encoded data.
+ *
+ * @param in
+ * a character array containing the Base64 encoded data.
+ * @return An array containing the decoded data bytes.
+ * @throws IllegalArgumentException
+ * if the input is not valid Base64 encoded data.
+ */
+ static byte[] decode(char[] in) {
+ int iLen = in.length;
+ if (iLen % 4 != 0) {
+ throw new IllegalArgumentException(
+ "Length of Base64 encoded input string is not a multiple of 4.");
+ }
+ while (iLen > 0 && in[iLen - 1] == '=') {
+ iLen--;
+ }
+ int oLen = (iLen * 3) / 4;
+ byte[] out = new byte[oLen];
+ int ip = 0;
+ int op = 0;
+ while (ip < iLen) {
+ int i0 = in[ip++];
+ int i1 = in[ip++];
+ int i2 = ip < iLen ? in[ip++] : 'A';
+ int i3 = ip < iLen ? in[ip++] : 'A';
+ if (i0 > 127 || i1 > 127 || i2 > 127 || i3 > 127) {
+ throw new IllegalArgumentException(
+ "Illegal character in Base64 encoded data.");
+ }
+ int b0 = map2[i0];
+ int b1 = map2[i1];
+ int b2 = map2[i2];
+ int b3 = map2[i3];
+ if (b0 < 0 || b1 < 0 || b2 < 0 || b3 < 0) {
+ throw new IllegalArgumentException(
+ "Illegal character in Base64 encoded data.");
+ }
+ int o0 = (b0 << 2) | (b1 >>> 4);
+ int o1 = ((b1 & 0xf) << 4) | (b2 >>> 2);
+ int o2 = ((b2 & 3) << 6) | b3;
+ out[op++] = (byte) o0;
+ if (op < oLen) {
+ out[op++] = (byte) o1;
+ }
+ if (op < oLen) {
+ out[op++] = (byte) o2;
+ }
+ }
+ return out;
+ }
+
+ // Dummy constructor.
+ private Base64Coder() {
+ }
+}
diff --git a/OSJ Forum/src/org/xmlrpc/android/IXMLRPCSerializer.java b/OSJ Forum/src/org/xmlrpc/android/IXMLRPCSerializer.java
new file mode 100644
index 0000000..f651e46
--- /dev/null
+++ b/OSJ Forum/src/org/xmlrpc/android/IXMLRPCSerializer.java
@@ -0,0 +1,32 @@
+package org.xmlrpc.android;
+
+import java.io.IOException;
+
+import org.xmlpull.v1.XmlPullParser;
+import org.xmlpull.v1.XmlPullParserException;
+import org.xmlpull.v1.XmlSerializer;
+
+public interface IXMLRPCSerializer {
+ String TAG_NAME = "name";
+ String TAG_MEMBER = "member";
+ String TAG_VALUE = "value";
+ String TAG_DATA = "data";
+
+ String TYPE_INT = "int";
+ String TYPE_I4 = "i4";
+ String TYPE_I8 = "i8";
+ String TYPE_DOUBLE = "double";
+ String TYPE_BOOLEAN = "boolean";
+ String TYPE_STRING = "string";
+ String TYPE_DATE_TIME_ISO8601 = "dateTime.iso8601";
+ String TYPE_BASE64 = "base64";
+ String TYPE_ARRAY = "array";
+ String TYPE_STRUCT = "struct";
+ // This added by mattias.ellback as part of issue #19
+ String TYPE_NULL = "nil";
+
+ String DATETIME_FORMAT = "yyyyMMdd'T'HH:mm:ss";
+
+ void serialize(XmlSerializer serializer, Object object) throws IOException;
+ Object deserialize(XmlPullParser parser) throws XmlPullParserException, IOException;
+}
diff --git a/OSJ Forum/src/org/xmlrpc/android/MethodCall.java b/OSJ Forum/src/org/xmlrpc/android/MethodCall.java
new file mode 100644
index 0000000..d573d5c
--- /dev/null
+++ b/OSJ Forum/src/org/xmlrpc/android/MethodCall.java
@@ -0,0 +1,20 @@
+package org.xmlrpc.android;
+
+import java.util.ArrayList;
+
+public class MethodCall {
+
+ private static final int TOPIC = 1;
+ String methodName;
+ ArrayList
+ * You can also pass as a parameter any object implementing XMLRPCSerializable interface. In this + * case your object overrides getSerializable() telling how to serialize to XMLRPC protocol + *
+ */ + +public class XMLRPCClient extends XMLRPCCommon { + private HttpClient client; + private HttpPost postMethod; + private HttpParams httpParams; + // These variables used in the code inspired by erickok in issue #6 + private boolean httpPreAuth = false; + private String username = ""; + private String password = ""; + + /** + * XMLRPCClient constructor. Creates new instance based on server URI + * (Code contributed by sgayda2 from issue #17, and by erickok from ticket #10) + * + * @param XMLRPC server URI + */ + public XMLRPCClient(URI uri) { + SchemeRegistry registry = new SchemeRegistry(); + registry.register(new Scheme("http", new PlainSocketFactory(), 80)); + registry.register(new Scheme("https", SSLSocketFactory.getSocketFactory(), 443)); + + postMethod = new HttpPost(uri); + postMethod.addHeader("Content-Type", "text/xml"); + + // WARNING + // I had to disable "Expect: 100-Continue" header since I had + // two second delay between sending http POST request and POST body + httpParams = postMethod.getParams(); + HttpProtocolParams.setUseExpectContinue(httpParams, false); + this.client = new DefaultHttpClient(new ThreadSafeClientConnManager(httpParams, registry), httpParams); + } + + /** + * XMLRPCClient constructor. Creates new instance based on server URI + * (Code contributed by sgayda2 from issue #17) + * + * @param XMLRPC server URI + * @param HttpClient to use + */ + + public XMLRPCClient(URI uri, HttpClient client) { + postMethod = new HttpPost(uri); + postMethod.addHeader("Content-Type", "text/xml"); + + // WARNING + // I had to disable "Expect: 100-Continue" header since I had + // two second delay between sending http POST request and POST body + httpParams = postMethod.getParams(); + HttpProtocolParams.setUseExpectContinue(httpParams, false); + this.client = client; + } + + /** + * Amends user agent + * (Code contributed by mortenholdflod from issue #28) + * + * @param userAgent defining the new User Agent string + */ + public void setUserAgent(String userAgent) { + postMethod.removeHeaders("User-Agent"); + postMethod.addHeader("User-Agent", userAgent); + } + + /** + * Convenience constructor. Creates new instance based on server String address + * @param XMLRPC server address + */ + public XMLRPCClient(String url) { + this(URI.create(url)); + } + + /** + * Convenience constructor. Creates new instance based on server String address + * @param XMLRPC server address + * @param HttpClient to use + */ + public XMLRPCClient(String url, HttpClient client) { + this(URI.create(url), client); + } + + + /** + * Convenience XMLRPCClient constructor. Creates new instance based on server URL + * @param XMLRPC server URL + */ + public XMLRPCClient(URL url) { + this(URI.create(url.toExternalForm())); + } + + /** + * Convenience XMLRPCClient constructor. Creates new instance based on server URL + * @param XMLRPC server URL + * @param HttpClient to use + */ + public XMLRPCClient(URL url, HttpClient client) { + this(URI.create(url.toExternalForm()), client); + } + + /** + * Convenience constructor. Creates new instance based on server String address + * @param XMLRPC server address + * @param HTTP Server - Basic Authentication - Username + * @param HTTP Server - Basic Authentication - Password + */ + public XMLRPCClient(URI uri, String username, String password) { + this(uri); + + ((DefaultHttpClient) client).getCredentialsProvider().setCredentials( + new AuthScope(uri.getHost(), uri.getPort(),AuthScope.ANY_REALM), + new UsernamePasswordCredentials(username, password)); + } + + /** + * Convenience constructor. Creates new instance based on server String address + * @param XMLRPC server address + * @param HTTP Server - Basic Authentication - Username + * @param HTTP Server - Basic Authentication - Password + * @param HttpClient to use + */ + public XMLRPCClient(URI uri, String username, String password, HttpClient client) { + this(uri, client); + + ((DefaultHttpClient) this.client).getCredentialsProvider().setCredentials( + new AuthScope(uri.getHost(), uri.getPort(),AuthScope.ANY_REALM), + new UsernamePasswordCredentials(username, password)); + } + + /** + * Convenience constructor. Creates new instance based on server String address + * @param XMLRPC server address + * @param HTTP Server - Basic Authentication - Username + * @param HTTP Server - Basic Authentication - Password + */ + public XMLRPCClient(String url, String username, String password) { + this(URI.create(url), username, password); + } + + /** + * Convenience constructor. Creates new instance based on server String address + * @param XMLRPC server address + * @param HTTP Server - Basic Authentication - Username + * @param HTTP Server - Basic Authentication - Password + * @param HttpClient to use + */ + public XMLRPCClient(String url, String username, String password, HttpClient client) { + this(URI.create(url), username, password, client); + } + + /** + * Convenience constructor. Creates new instance based on server String address + * @param XMLRPC server url + * @param HTTP Server - Basic Authentication - Username + * @param HTTP Server - Basic Authentication - Password + */ + public XMLRPCClient(URL url, String username, String password) { + this(URI.create(url.toExternalForm()), username, password); + } + + /** + * Convenience constructor. Creates new instance based on server String address + * @param XMLRPC server url + * @param HTTP Server - Basic Authentication - Username + * @param HTTP Server - Basic Authentication - Password + * @param HttpClient to use + */ + public XMLRPCClient(URL url, String username, String password, HttpClient client) { + this(URI.create(url.toExternalForm()), username, password, client); + } + + /** + * Sets basic authentication on web request using plain credentials + * @param username The plain text username + * @param password The plain text password + * @param doPreemptiveAuth Select here whether to authenticate without it being requested first by the server. + */ + public void setBasicAuthentication(String username, String password, boolean doPreemptiveAuth) { + // This code required to trigger the patch created by erickok in issue #6 + if(doPreemptiveAuth = true) { + this.httpPreAuth = doPreemptiveAuth; + this.username = username; + this.password = password; + } else { + ((DefaultHttpClient) client).getCredentialsProvider().setCredentials(new AuthScope(postMethod.getURI().getHost(), postMethod.getURI().getPort(), AuthScope.ANY_REALM), new UsernamePasswordCredentials(username, password)); + } + } + + /** + * Convenience Constructor: Sets basic authentication on web request using plain credentials + * @param username The plain text username + * @param password The plain text password + */ + public void setBasicAuthentication(String username, String password) { + setBasicAuthentication(username, password, false); + } + + /** + * Call method with optional parameters. This is general method. + * If you want to call your method with 0-8 parameters, you can use more + * convenience call() methods + * + * @param method name of method to call + * @param params parameters to pass to method (may be null if method has no parameters) + * @return deserialized method return value + * @throws XMLRPCException + */ + @SuppressWarnings("unchecked") + public Object callEx(String method, Object[] params) throws XMLRPCException { + try { + // prepare POST body + String body = methodCall(method, params); + + // set POST body + HttpEntity entity = new StringEntity(body); + postMethod.setEntity(entity); + + // This code slightly tweaked from the code by erickok in issue #6 + // Force preemptive authentication + // This makes sure there is an 'Authentication: ' header being send before trying and failing and retrying + // by the basic authentication mechanism of DefaultHttpClient + if(this.httpPreAuth == true) { + String auth = this.username + ":" + this.password; + postMethod.addHeader("Authorization", "Basic " + Base64Coder.encode(auth.getBytes()).toString()); + } + + //Log.d(Tag.LOG, "ros HTTP POST"); + // execute HTTP POST request + HttpResponse response = client.execute(postMethod); + //Log.d(Tag.LOG, "ros HTTP POSTed"); + + // check status code + int statusCode = response.getStatusLine().getStatusCode(); + //Log.d(Tag.LOG, "ros status code:" + statusCode); + if (statusCode != HttpStatus.SC_OK) { + throw new XMLRPCException("HTTP status code: " + statusCode + " != " + HttpStatus.SC_OK, statusCode); + } + + // parse response stuff + // + // setup pull parser + XmlPullParser pullParser = XmlPullParserFactory.newInstance().newPullParser(); + entity = response.getEntity(); + Reader reader = new InputStreamReader(new BufferedInputStream(entity.getContent())); +// for testing purposes only +// reader = new StringReader("