android-openrat

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs

commit fb46d0a62f950dbaff780f5c86d719e7c16e32f0
Author: dankert <devnull@localhost>
Date:   Wed, 28 Sep 2011 22:34:57 +0200

Erste Version des Blogging-Clients.

Diffstat:
.classpath | 7+++++++
.project | 33+++++++++++++++++++++++++++++++++
AndroidManifest.xml | 22++++++++++++++++++++++
default.properties | 13+++++++++++++
res/drawable-hdpi/icon.png | 0
res/drawable-ldpi/icon.png | 0
res/drawable-mdpi/icon.png | 0
res/layout/main.xml | 12++++++++++++
res/menu/main.xml | 5+++++
res/values/strings.xml | 6++++++
res/xml/preferences.xml | 6++++++
src/de/openrat/android/blog/Configuration.java | 15+++++++++++++++
src/de/openrat/android/blog/OpenRatBlog.java | 129+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
src/de/openrat/android/blog/client/CMSRequest.java | 396+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
14 files changed, 644 insertions(+), 0 deletions(-)

diff --git a/.classpath b/.classpath @@ -0,0 +1,7 @@ +<?xml version="1.0" encoding="UTF-8"?> +<classpath> + <classpathentry kind="src" path="src"/> + <classpathentry kind="src" path="gen"/> + <classpathentry kind="con" path="com.android.ide.eclipse.adt.ANDROID_FRAMEWORK"/> + <classpathentry kind="output" path="bin"/> +</classpath> diff --git a/.project b/.project @@ -0,0 +1,33 @@ +<?xml version="1.0" encoding="UTF-8"?> +<projectDescription> + <name>Blog1</name> + <comment></comment> + <projects> + </projects> + <buildSpec> + <buildCommand> + <name>com.android.ide.eclipse.adt.ResourceManagerBuilder</name> + <arguments> + </arguments> + </buildCommand> + <buildCommand> + <name>com.android.ide.eclipse.adt.PreCompilerBuilder</name> + <arguments> + </arguments> + </buildCommand> + <buildCommand> + <name>org.eclipse.jdt.core.javabuilder</name> + <arguments> + </arguments> + </buildCommand> + <buildCommand> + <name>com.android.ide.eclipse.adt.ApkBuilder</name> + <arguments> + </arguments> + </buildCommand> + </buildSpec> + <natures> + <nature>com.android.ide.eclipse.adt.AndroidNature</nature> + <nature>org.eclipse.jdt.core.javanature</nature> + </natures> +</projectDescription> diff --git a/AndroidManifest.xml b/AndroidManifest.xml @@ -0,0 +1,21 @@ +<?xml version="1.0" encoding="utf-8"?> +<manifest xmlns:android="http://schemas.android.com/apk/res/android" + package="de.openrat.android.blog" + android:versionCode="1" + android:versionName="1.0"> + <uses-permission android:name="android.permission.INTERNET" /> + + <application android:icon="@drawable/icon" android:label="@string/app_name"> + <activity android:name=".OpenRatBlog" + android:label="@string/app_name"> + <intent-filter> + <action android:name="android.intent.action.MAIN" /> + <category android:name="android.intent.category.LAUNCHER" /> + </intent-filter> + </activity> + + <activity android:name="Configuration"></activity> +</application> + + +</manifest> + \ No newline at end of file diff --git a/default.properties b/default.properties @@ -0,0 +1,13 @@ +# This file is automatically generated by Android Tools. +# Do not modify this file -- YOUR CHANGES WILL BE ERASED! +# +# This file must be checked in Version Control Systems. +# +# To customize properties used by the Ant build system use, +# "build.properties", and override values to adapt the script to your +# project structure. + +# Indicates whether an apk should be generated for each density. +split.density=false +# Project target. +target=android-6 diff --git a/res/drawable-hdpi/icon.png b/res/drawable-hdpi/icon.png Binary files differ. diff --git a/res/drawable-ldpi/icon.png b/res/drawable-ldpi/icon.png Binary files differ. diff --git a/res/drawable-mdpi/icon.png b/res/drawable-mdpi/icon.png Binary files differ. diff --git a/res/layout/main.xml b/res/layout/main.xml @@ -0,0 +1,12 @@ +<?xml version="1.0" encoding="utf-8"?> +<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" + android:orientation="vertical" + android:layout_width="fill_parent" + android:layout_height="fill_parent" + > +<TextView + android:layout_width="fill_parent" + android:layout_height="wrap_content" + android:text="@string/hello" + /> +</LinearLayout> diff --git a/res/menu/main.xml b/res/menu/main.xml @@ -0,0 +1,4 @@ +<menu xmlns:android="http://schemas.android.com/apk/res/android"> + <item android:id="@+id/menu_preferences" android:title="@string/preferences"></item> +</menu> + + \ No newline at end of file diff --git a/res/values/strings.xml b/res/values/strings.xml @@ -0,0 +1,6 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <string name="hello">Hello World, OpenRatBlog!</string> + <string name="app_name"></string> +<string name="preferences">Einstellungen</string> +</resources> diff --git a/res/xml/preferences.xml b/res/xml/preferences.xml @@ -0,0 +1,6 @@ +<?xml version="1.0" encoding="utf-8"?> +<PreferenceScreen + xmlns:android="http://schemas.android.com/apk/res/android"> +<PreferenceCategory><EditTextPreference android:key="server" android:title="Server"></EditTextPreference> +</PreferenceCategory> +</PreferenceScreen> diff --git a/src/de/openrat/android/blog/Configuration.java b/src/de/openrat/android/blog/Configuration.java @@ -0,0 +1,15 @@ +package de.openrat.android.blog; + +import android.os.Bundle; +import android.preference.PreferenceActivity; + +public class Configuration extends PreferenceActivity +{ + + @Override + protected void onCreate(Bundle savedInstanceState) + { + super.onCreate(savedInstanceState); + addPreferencesFromResource(R.xml.preferences); + } +} diff --git a/src/de/openrat/android/blog/OpenRatBlog.java b/src/de/openrat/android/blog/OpenRatBlog.java @@ -0,0 +1,128 @@ +package de.openrat.android.blog; + +import java.io.IOException; + +import org.json.JSONObject; + +import android.app.Activity; +import android.content.Intent; +import android.content.SharedPreferences; +import android.os.Bundle; +import android.view.Menu; +import android.view.MenuInflater; +import android.view.MenuItem; +import android.widget.ScrollView; +import android.widget.TextView; +import de.openrat.android.blog.client.CMSRequest; + +public class OpenRatBlog extends Activity +{ + private static final String PREFS_NAME = "OR_BLOG_PREFS"; + + /** Called when the activity is first created. */ + @Override + public void onCreate(Bundle savedInstanceState) + { + super.onCreate(savedInstanceState); + setContentView(R.layout.main); + + CMSRequest request = new CMSRequest("demo.openrat.de"); + + request.setParameter("action", "index"); + request.setParameter("subaction", "login"); + request.setParameter("dbid", "db1"); + request.setParameter("login_name", "admin"); + request.setParameter("login_password", "admin"); + String response = null; + try + { + response = request.performRequest(); + + } catch (IOException e) + { + response = e.getMessage(); + } + + try + { + JSONObject json = new JSONObject(response); + JSONObject session = json.getJSONObject("session"); + final String sessionName = session.getString("name"); + final String sessionId = session.getString("id"); + + final String msgText = json.getJSONArray("notices") + .getJSONObject(0).getString("text"); +// final String msgText2 = json.getJSONArray("notics") +// .getJSONObject(0).getString("text"); + + // TextView text = new TextView(this); + // text.setText("Sitzung '" + sessionId + "': " + sessionId); + + request.setCookie(sessionName, sessionId); + TextView tv = new TextView(this); + tv.setVerticalScrollBarEnabled(true); + tv.setHorizontalScrollBarEnabled(true); + tv.setScrollBarStyle(TextView.SCROLLBARS_INSIDE_INSET); + tv.setText(msgText + "\nSitzung '" + sessionName + "': " + + sessionId + "\nAusgabe: " + response); + + ScrollView scrollView =new ScrollView(this); + scrollView.setScrollContainer(true); + scrollView.setFocusable(true); + scrollView.addView(tv); + + setContentView(scrollView); + + } catch (Exception e) + { + response = e.getMessage(); + + TextView tv = new TextView(this); + tv.setText("Fehler: " + response); + setContentView(tv); + + } + + // Restore preferences + // SharedPreferences settings = getSharedPreferences(PREFS_NAME, 0); + // boolean silent = settings.getBoolean("silentMode", false); + + } + + @Override + public boolean onCreateOptionsMenu(Menu menu) + { + super.onCreateOptionsMenu(menu); + MenuInflater mi = new MenuInflater(getApplication()); + mi.inflate(R.menu.main, menu); + + return true; + } + + + public boolean onOptionsItemSelected(MenuItem item) + { + switch (item.getItemId()) + { + case R.id.menu_preferences: + startActivity( new Intent(this,Configuration.class)); + } + return false; + } + + @Override + protected void onStop() + { + super.onStop(); + + // Save user preferences. We need an Editor object to + // make changes. All objects are from android.context.Context + SharedPreferences settings = getSharedPreferences(PREFS_NAME, 0); + SharedPreferences.Editor editor = settings.edit(); + // editor.putBoolean("silentMode", mSilentMode); + + // Don't forget to commit your edits!!! + editor.commit(); + } + +}+ \ No newline at end of file diff --git a/src/de/openrat/android/blog/client/CMSRequest.java b/src/de/openrat/android/blog/client/CMSRequest.java @@ -0,0 +1,396 @@ +/* +OpenRat Java-Client +Copyright (C) 2009 Jan Dankert + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Library General Public +License as published by the Free Software Foundation; either +version 2 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 +Library General Public License for more details. + +You should have received a copy of the GNU Library General Public +License along with this library; if not, write to the +Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, +Boston, MA 02110-1301, USA. + + */ +package de.openrat.android.blog.client; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.PrintWriter; +import java.io.StringReader; +import java.io.UnsupportedEncodingException; +import java.net.InetSocketAddress; +import java.net.Socket; +import java.net.SocketAddress; +import java.net.URLEncoder; +import java.util.HashMap; +import java.util.Locale; +import java.util.Map; +import java.util.Map.Entry; + +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory; +import javax.xml.parsers.ParserConfigurationException; + +import org.w3c.dom.Document; +import org.xml.sax.InputSource; +import org.xml.sax.SAXException; + +/** + * API-Request to the OpenRat Content Management System. <br> + * <br> + * The call to the CMS server is done via a (non-SSL) HTTP connection.<br> + * <br> + * Before a call you are able to set some key/value-pairs as parameters. After calling the CMS a + * DOM-document is returned, which contains the server response.<br> + * Example <br> + * + * <pre> + * CMSRequest request = new CMSRequest(&quot;your.openrat.example.com&quot;); + * //prints tracing information to stdout. + * request.trace = true; + * try { + * request.parameter.put(&quot;action&quot;, &quot;index&quot;); + * request.parameter.put(&quot;subaction&quot;, &quot;showlogin&quot;); // login page + * request.parameter.put(&quot;...&quot;, &quot;...&quot;); + * Document response = request.call(); + * // now traverse through the dom tree and get your information. + * } + * catch (IOException e) { + * // your error handling. + * } + * </pre> + * + * @author Jan Dankert + */ +public class CMSRequest { + + // some constants... + private static final String CHARSET_UTF8 = "UTF-8"; + private static final String HTTP_GET = "GET"; + private static final String HTTP_POST = "POST"; + + /** + * if <code>true</code>, Tracing-Output will be logged to stdout. Default: <code>false</code>. + */ + // this is public, for easier use. + public boolean trace = false; + + /** + * HTTP-method, must be "GET" or "POST", default: "GET". + */ + private String method = HTTP_GET; + + /** + * Parameter map. + */ + private Map<String, String> parameter = new HashMap<String, String>(); + + private String serverPath; + private String serverHost; + private int serverPort; + + private String proxyHostname; + private int proxyPort; + private SocketAddress socketAddress; + + private String cookieName; + private String cookieValue; + private String language; + + + /** + * + */ + public CMSRequest() + { + super(); + this.language = Locale.getDefault().getLanguage(); + } + + public String getLanguage() + { + return language; + } + + public void setLanguage(String language) + { + this.language = language; + } + + /** + * Setting a HTTP-Cookie. + * + * @param name name + * @param value value + */ + public void setCookie(String name, String value) { + + this.cookieName = this.urlEncode(name); + this.cookieValue = this.urlEncode(value); + } + + /** + * URL-Encoder. + * + * @param value + * @return url-encoded value + */ + private String urlEncode(String value) { + + try { + return URLEncoder.encode(value, CHARSET_UTF8); + } + catch (UnsupportedEncodingException e) { + // maybe... this would be strange + throw new IllegalStateException(CHARSET_UTF8 + " ist not supported by this VM"); + } + } + + /** + * Setting a HTTP-Proxy. + * + * @param host hostname + * @param port port + */ + public void setProxy(String host, int port) { + + this.proxyHostname = host; + this.proxyPort = port; + } + + /** + * Set the HTTP Method. Default is "GET". + * + * @param method HTTP-method + */ + public void setMethod(String method) { + + if (!HTTP_GET.equalsIgnoreCase(method) && !HTTP_POST.equalsIgnoreCase(method)) + throw new IllegalArgumentException("Method must be '" + HTTP_POST + "' or '" + HTTP_GET + + "'."); + + this.method = method.toUpperCase(); + } + + /** + * Clear parameter values. + */ + public void clearParameters() { + + parameter.clear(); + } + + /** + * Setting a parameter value. <strong>DO NOT url-encode your values</strong> as this is done + * automatically inside this method! + * + * @param paramName name + * @param paramValue value + */ + public void setParameter(String paramName, String paramValue) { + + if (paramName == null || paramValue == null || "" == paramName) + throw new IllegalArgumentException("parameter name and value must have values"); + + parameter.put(paramName, paramValue); + } + + /** + * Constructs a CMS-Request to the specified server.<br> + * Server-Path is "/", Server-Port is 80. + * + * @param host hostname + */ + public CMSRequest(String host) { + + super(); + this.serverHost = host; + this.serverPath = "/"; + this.serverPort = 80; + } + + /** + * Constructs a CMS-Request to the specified server/path.<br> + * Server-Port is 80. + * + * @param host hostname + * @param path path + */ + public CMSRequest(String host, String path) { + + super(); + this.serverHost = host; + this.serverPath = path; + this.serverPort = 80; + } + + /** + * Constructs a CMS-Request to the specified server/path/port. + * + * @param host hostname + * @param path path + * @param port port-number + */ + public CMSRequest(String host, String path, int port) { + + super(); + this.serverHost = host; + this.serverPath = path; + this.serverPort = port; + } + + /** + * Sends a request to the openrat-server and parses the response into a DOM tree document. + * + * @return server response as a DOM tree + * @throws IOException if server is unrechable or responds non-wellformed XML + */ + public String performRequest() throws IOException { + + final Socket socket = new Socket(); + + try { + + final boolean useProxy = this.proxyHostname != null; + final boolean useCookie = this.cookieName != null; + + if (serverPath == null) + this.serverPath = "/"; + if (!serverPath.startsWith("/")) + this.serverPath = "/" + this.serverPath; + + // When a client uses a proxy, it typically sends all requests to that proxy, instead + // of to the servers in the URLs. Requests to a proxy differ from normal requests in one + // way: in the first line, they use the complete URL of the resource being requested, + // instead of just the path. + if (useProxy) { + socketAddress = new InetSocketAddress(this.proxyHostname, this.proxyPort); + } else { + socketAddress = new InetSocketAddress(this.serverHost, serverPort); + } + + socket.setKeepAlive(false); + socket.setReuseAddress(false); + socket.connect(socketAddress, 5000); + + final StringBuffer header = new StringBuffer(); + + final StringBuffer parameterList = new StringBuffer(); + + for (Entry<String, String> entry : this.parameter.entrySet()) { + if (parameterList.length() > 0) + parameterList.append("&"); + parameterList.append(this.urlEncode(entry.getKey())); + parameterList.append("="); + parameterList.append(this.urlEncode(entry.getValue())); + } + + String httpUrl = this.serverPath; + + if (useProxy) + // See RFC 2616 Section 5.1.2 "Request-URI" + // "The absolute URI form is REQUIRED when the request is being made to a proxy" + httpUrl = "http://" + this.serverHost + httpUrl; + + if (HTTP_GET.equals(this.method)) + httpUrl = httpUrl + "?" + parameterList; + + // using HTTP/1.0 as this is supported by all HTTP-servers and proxys. + // We have no need for HTTP/1.1 at the moment. + header.append(this.method + " " + httpUrl + " HTTP/1.0\n"); + + // Setting the HTTP Header + header.append("Host: " + this.serverHost + "\n"); + header.append("User-Agent: Mozilla/5.0; compatible (OpenRat android-client)\n"); + header.append("Accept: application/json\n"); + header.append("Accept-Language: " + language + "\n"); + header.append("Accept-Charset: utf-8\n"); + header.append("Connection: close\n"); + if (useCookie) + header.append("Cookie: " + cookieName + "=" + cookieValue + "\n"); + + if (HTTP_POST.equals(this.method)) { + header.append("Content-Type: application/x-www-form-urlencoded" + "\n"); + header.append("Content-Length: " + parameterList.length() + "\n"); + } + + header.append("\n"); + + if (HTTP_POST.equals(this.method)) + header.append(parameterList); + + if (this.trace) + System.out.println("--- request ---"); + if (this.trace) + System.out.println(header.toString()); + + final PrintWriter printWriter = new PrintWriter(socket.getOutputStream(), true); + printWriter.write(header.toString()); + printWriter.flush(); + + final InputStream inputStream = socket.getInputStream(); + final int available = inputStream.available(); + + final BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(socket + .getInputStream())); + + final String httpResponse = bufferedReader.readLine().trim(); + final String httpRetCode = httpResponse.substring(9, 12); + + if (this.trace) + System.out.println("--- response ---"); + if (this.trace) + System.out.println(httpResponse); + + // Check if we got the status 200=OK. + if (!httpRetCode.equals("200")) { + + // non-200-status seems to be an error. + throw new IOException("No HTTP 200: Status=" + httpRetCode + " (" + httpResponse + + ")"); + } + + while (true) { + + String responseHeader = bufferedReader.readLine().trim(); + + if (responseHeader.equals("")) + break; + + if (this.trace) + System.out.println(responseHeader); + } + + StringBuffer response = new StringBuffer(); + while (bufferedReader.ready()) { + + response.append(bufferedReader.readLine() + "\n"); + } + socket.close(); + + if (this.trace) + System.out.println("--- response body ---"); + if (this.trace) + System.out.println(response + "\n\n\n"); + + return response.toString(); + } + finally { + try { + socket.close(); // Clean up the socket. + } + catch (IOException e) { + // We have done our very best. + } + } + } +}