android-openrat

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

commit 74f4035a61471e3153f79b047505b69eb9db7ea1
parent 439f240b4820ba55f3d86bff62959aca2412f7e7
Author: dankert <devnull@localhost>
Date:   Fri, 14 Oct 2011 22:56:16 +0200

Upload von Dateien, diverse Erweiterungen.

Diffstat:
res/drawable/icon_file.png | 0
res/drawable/icon_folder.png | 0
res/drawable/icon_link.png | 0
res/drawable/icon_page.png | 0
res/drawable/icon_project.png | 0
res/layout/listing_entry.xml | 25+++++++++++++++++--------
res/menu/context.xml | 6++++++
res/menu/folder.xml | 9+++++++++
res/values/strings.xml | 10++++++++++
src/de/openrat/android/blog/FolderActivity.java | 358++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-----
src/de/openrat/android/blog/FolderEntry.java | 17+++++++++++++++++
src/de/openrat/android/blog/OpenRatBlog.java | 4++++
src/de/openrat/android/blog/ProjectActivity.java | 43+++++++++++++++++++++++++------------------
src/de/openrat/android/blog/adapter/FSimpleAdapter.java | 27---------------------------
src/de/openrat/android/blog/adapter/FolderContentAdapter.java | 104+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
src/de/openrat/android/blog/client/CMSRequest.java | 399++++++++++++-------------------------------------------------------------------
src/de/openrat/android/blog/client/HTTPRequest.java | 588+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
17 files changed, 1173 insertions(+), 417 deletions(-)

diff --git a/res/drawable/icon_file.png b/res/drawable/icon_file.png Binary files differ. diff --git a/res/drawable/icon_folder.png b/res/drawable/icon_folder.png Binary files differ. diff --git a/res/drawable/icon_link.png b/res/drawable/icon_link.png Binary files differ. diff --git a/res/drawable/icon_page.png b/res/drawable/icon_page.png Binary files differ. diff --git a/res/drawable/icon_project.png b/res/drawable/icon_project.png Binary files differ. diff --git a/res/layout/listing_entry.xml b/res/layout/listing_entry.xml @@ -1,13 +1,22 @@ <?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" android:padding="10sp"> + android:orientation="horizontal" android:layout_width="fill_parent" + android:layout_height="fill_parent" android:padding="5sp"> - <TextView android:text="@+id/TextView03" android:layout_width="wrap_content" - android:layout_height="wrap_content" android:id="@+id/listentry_name" - android:textSize="16sp"></TextView> - <TextView android:text="@+id/TextView01" android:layout_width="wrap_content" - android:layout_height="wrap_content" android:id="@+id/listentry_description" - android:textSize="14sp"></TextView> + <ImageView android:id="@+id/listentry_image" + android:layout_width="wrap_content" android:layout_height="wrap_content" android:padding="20sp"> + </ImageView> + + <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" + android:orientation="vertical" android:layout_width="fill_parent" + android:layout_height="wrap_content" android:paddingLeft="5sp"> + + <TextView android:text="@+id/TextView03" + android:layout_width="wrap_content" android:layout_height="wrap_content" + android:id="@+id/listentry_name" android:textSize="16sp"></TextView> + <TextView android:text="@+id/TextView01" + android:layout_width="wrap_content" android:layout_height="wrap_content" + android:id="@+id/listentry_description" android:textSize="14sp"></TextView> + </LinearLayout> </LinearLayout> diff --git a/res/menu/context.xml b/res/menu/context.xml @@ -0,0 +1,5 @@ +<menu xmlns:android="http://schemas.android.com/apk/res/android"> + <item android:id="@+id/menu_properties" android:title="@string/properties"></item> + <item android:id="@+id/menu_publish" android:title="@string/publish"></item> +</menu> + + \ No newline at end of file diff --git a/res/menu/folder.xml b/res/menu/folder.xml @@ -0,0 +1,8 @@ +<menu xmlns:android="http://schemas.android.com/apk/res/android"> + <item android:id="@+id/menu_language" android:title="@string/language"></item> + <item android:id="@+id/menu_model" android:title="@string/model"></item> + <item android:id="@+id/menu_new" android:title="@string/new1"></item> + <item android:id="@+id/menu_upload" android:title="@string/upload"></item> + <item android:id="@+id/menu_upload_image" android:title="@string/upload_image"></item> +</menu> + + \ No newline at end of file diff --git a/res/values/strings.xml b/res/values/strings.xml @@ -21,4 +21,14 @@ </string-array> <string name="writable">Schreibzugriff</string> <string name="version_summary">Server-Version</string> + + <string name="publish">Veröffentlichen</string> + <string name="properties">Eigenschaften</string> + <string name="loading">Warten auf Server</string> + <string name="waiting">Inhalt wird geladen</string> + <string name="language">Sprache</string> + <string name="model">Variante</string> + <string name="new1">Neu</string> + <string name="upload">Datei hochladen</string> + <string name="upload_image">Bild hochladen</string> </resources> diff --git a/src/de/openrat/android/blog/FolderActivity.java b/src/de/openrat/android/blog/FolderActivity.java @@ -3,24 +3,42 @@ */ package de.openrat.android.blog; +import java.io.BufferedInputStream; +import java.io.BufferedReader; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileReader; import java.io.IOException; +import java.io.PrintStream; import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; import org.json.JSONArray; +import org.json.JSONException; import org.json.JSONObject; +import android.app.AlertDialog; import android.app.ListActivity; +import android.app.ProgressDialog; +import android.content.DialogInterface; import android.content.Intent; +import android.content.DialogInterface.OnClickListener; +import android.database.Cursor; +import android.net.Uri; import android.os.Bundle; +import android.provider.MediaStore; +import android.view.ContextMenu; +import android.view.Menu; +import android.view.MenuInflater; +import android.view.MenuItem; import android.view.View; +import android.view.View.OnCreateContextMenuListener; import android.widget.AdapterView; import android.widget.ListAdapter; import android.widget.ListView; -import android.widget.SimpleAdapter; +import android.widget.Toast; import android.widget.AdapterView.OnItemClickListener; +import de.openrat.android.blog.FolderEntry.FType; +import de.openrat.android.blog.adapter.FolderContentAdapter; import de.openrat.android.blog.client.CMSRequest; /** @@ -30,12 +48,16 @@ import de.openrat.android.blog.client.CMSRequest; public class FolderActivity extends ListActivity { + private static final String BOUNDARY = "usadlkuuusdkcua43sfd"; private static final String ID2 = "id"; public static final String CLIENT = "client"; private static final String NAME = "name"; + private static final String TYP = "type"; private static final String DESCRIPTION = "description"; + private static final int ACTIVITY_CHOOSE_FILE = 1; + private static final int ACTIVITY_CHOOSE_IMAGE = 2; private CMSRequest request; - private List<Map<String, String>> data; + private ArrayList<FolderEntry> data; @Override protected void onCreate(Bundle savedInstanceState) @@ -49,22 +71,64 @@ public class FolderActivity extends ListActivity ; String[] from = new String[] { NAME, DESCRIPTION }; ; - data = new ArrayList<Map<String, String>>(); + data = new ArrayList<FolderEntry>(); request = (CMSRequest) getIntent().getSerializableExtra(CLIENT); // + String folderid = getIntent().getStringExtra("folderid"); + String response = null; + if (folderid == null) + { + request.clearParameters(); + request.setParameter("action", "tree"); + request.setParameter("subaction", "load"); + + try + { + response = request.performRequest(); + System.out.println("Ordnerinhalt: " + response); + JSONObject json = new JSONObject(response); + folderid = json.getJSONArray("zeilen").getJSONObject(1) + .getString("name"); + // JSONObject inhalte = json.getJSONObject("object"); + // folderid = ...; + + } catch (IOException e) + { + System.err.println("Fuck Folder"); + System.err.println(response); + System.err.println(e.getMessage()); + } catch (JSONException e) + { + // TODO Auto-generated catch block + e.printStackTrace(); + } + } + System.out.println("Folderid: " + folderid); + request.clearParameters(); + request.setParameter("id", folderid); + request.setParameter("action", "folder"); request.setParameter("subaction", "show"); - String folderid = getIntent().getStringExtra("folderid"); - request.setParameter("id", folderid != null ? folderid : "1"); - String response = null; + response = null; try { + ProgressDialog dialog = ProgressDialog.show(FolderActivity.this, + getResources().getString(R.string.loading), getResources() + .getString(R.string.waiting)); + // try + // { + // Thread.sleep(2000L); + // } catch (InterruptedException e) + // { + // e.printStackTrace(); + // } response = request.performRequest(); System.out.println("Ordnerinhalt: " + response); + dialog.dismiss(); } catch (IOException e) { @@ -83,12 +147,12 @@ public class FolderActivity extends ListActivity { JSONObject obj = inhalte.getJSONObject(names.getString(i)); - final Map<String, String> values = new HashMap<String, String>(); - values.put(NAME, "[" + obj.getString("type") + "] " - + obj.getString("name")); - values.put(DESCRIPTION, obj.getString("desc")); - values.put(ID2, names.getString(i)); - data.add(values); + final FolderEntry entry = new FolderEntry(); + entry.type = FType.valueOf(obj.getString("type").toUpperCase()); + entry.name = obj.getString("name"); + entry.description = obj.getString("desc"); + entry.id = names.getString(i); + data.add(entry); } @@ -97,8 +161,9 @@ public class FolderActivity extends ListActivity e.printStackTrace(); } - final ListAdapter adapter = new SimpleAdapter(this, data, - R.layout.listing_entry, from, to); + // final ListAdapter adapter = new SimpleAdapter(this, data, + // R.layout.listing_entry, from, to); + final ListAdapter adapter = new FolderContentAdapter(this, data); setListAdapter(adapter); ListView list = getListView(); @@ -110,13 +175,262 @@ public class FolderActivity extends ListActivity public void onItemClick(AdapterView<?> parent, View view, int position, long id) { - final Intent i = new Intent(FolderActivity.this, - FolderActivity.class); - i.putExtra(CLIENT, request); - i.putExtra("folderid", data.get(position).get(ID2)); - startActivity(i); + FolderEntry entry = data.get(position); + + final Intent intent; + switch (entry.type) + { + case FOLDER: + + intent = new Intent(FolderActivity.this, + FolderActivity.class); + intent.putExtra(CLIENT, request); + intent.putExtra("folderid", entry.id); + startActivity(intent); + break; + case PAGE: + intent = new Intent(FolderActivity.this, + PageElementsActivity.class); + intent.putExtra(CLIENT, request); + intent.putExtra("pageid", entry.id); + startActivity(intent); + default: + } } }); + + list.setOnCreateContextMenuListener(new OnCreateContextMenuListener() + { + + @Override + public void onCreateContextMenu(ContextMenu menu, View v, + ContextMenu.ContextMenuInfo menuInfo) + { + MenuInflater menuInflater = getMenuInflater(); + menuInflater.inflate(R.menu.context, menu); + // menu.add(0, 5, 0, "Click Me"); + + } + + }); + /** + * + list.setonOnItemLongClickListener(new OnItemLongClickListener() { + * + * @Override public boolean onItemLongClick(AdapterView<?> parent, View + * view, int position, long id) { Map<String, String> entry = + * data.get(position); + * + * final Intent intent; intent = new + * Intent(FolderActivity.this, PropertiesActivity.class); + * intent.putExtra(CLIENT, request); + * intent.putExtra("objectid", entry.get(ID2)); + * startActivity(intent); return true; } }); + */ } + public boolean onContextItemSelected(MenuItem item) + { + + switch (item.getItemId()) + { + + case R.id.menu_properties: + + // This is actually where the magic happens. + + // As we use an adapter view (which the ListView is) + + // We can cast item.getMenuInfo() to AdapterContextMenuInfo + + AdapterView.AdapterContextMenuInfo menuInfo = (AdapterView.AdapterContextMenuInfo) item + .getMenuInfo(); + + // To get the id of the clicked item in the list use menuInfo.id + + // Log.d("t", "list pos:" + menuInfo.position + " id:" + + // menuInfo.id); + FolderEntry entry = data.get(menuInfo.position); + final Intent intent; + intent = new Intent(FolderActivity.this, PropertiesActivity.class); + intent.putExtra(CLIENT, request); + intent.putExtra("objectid", entry.id); + intent.putExtra(TYP, entry.type); + startActivity(intent); + return true; + + case R.id.menu_publish: + + // This is actually where the magic happens. + + // As we use an adapter view (which the ListView is) + + // We can cast item.getMenuInfo() to AdapterContextMenuInfo + + menuInfo = (AdapterView.AdapterContextMenuInfo) item.getMenuInfo(); + + // To get the id of the clicked item in the list use menuInfo.id + + entry = data.get(menuInfo.position); + Toast.makeText(this, R.string.publish, Toast.LENGTH_SHORT); + + return true; + + default: + + return super.onContextItemSelected(item); + + } + + // return true; + + } + + @Override + public boolean onCreateOptionsMenu(Menu menu) + { + super.onCreateOptionsMenu(menu); + MenuInflater mi = new MenuInflater(getApplication()); + mi.inflate(R.menu.folder, menu); + + return true; + } + + public boolean onOptionsItemSelected(MenuItem item) + { + switch (item.getItemId()) + { + case R.id.menu_language: + AlertDialog.Builder builder = new AlertDialog.Builder(this); + builder.setMessage(R.string.language).setCancelable(false) + .setPositiveButton("OK", + new DialogInterface.OnClickListener() + { + public void onClick(DialogInterface dialog, + int id) + { + // Speichern + } + }).setSingleChoiceItems(new String[] { "a", "b" }, + 1, new OnClickListener() + { + + @Override + public void onClick(DialogInterface dialog, + int which) + { + + } + }); + AlertDialog alert = builder.create(); + alert.show(); + return true; + + case R.id.menu_model: + + Toast.makeText(this, "Model", Toast.LENGTH_SHORT); + return true; + case R.id.menu_upload: + + Intent chooseFile; + Intent intent; + chooseFile = new Intent(Intent.ACTION_GET_CONTENT); + chooseFile.setType("file/*"); + intent = Intent.createChooser(chooseFile, "Choose a file"); + startActivityForResult(intent, ACTIVITY_CHOOSE_FILE); + return true; + case R.id.menu_upload_image: + + // Intent chooseFile; + // Intent intent; + chooseFile = new Intent(Intent.ACTION_GET_CONTENT); + chooseFile.setType("image/*"); + intent = Intent.createChooser(chooseFile, "Choose an image"); + startActivityForResult(intent, ACTIVITY_CHOOSE_IMAGE); + return true; + + default: + Toast.makeText(this, "??: " + item.getItemId(), Toast.LENGTH_SHORT); + + } + return false; + } + + @Override + protected void onActivityResult(int requestCode, int resultCode, Intent data) + { + switch (requestCode) + { + case ACTIVITY_CHOOSE_FILE: + case ACTIVITY_CHOOSE_IMAGE: + { + if (resultCode == RESULT_OK) + { + + Uri uri = data.getData(); + + String filePath; + if (requestCode == ACTIVITY_CHOOSE_IMAGE) + { + + filePath = getPath(uri); + } else + { + filePath = uri.getPath(); + } + + System.out.println(filePath); + + request.clearParameters(); + request.setAction("folder"); + request.setActionMethod("createnewfile"); + request.setMethod("POST"); + request.trace = true; + + try + { + final File file = new File(filePath); + BufferedInputStream br = new BufferedInputStream( + new FileInputStream(file)); + + StringBuffer fileContent = new StringBuffer(); + // create a byte array + byte[] contents = new byte[1024]; + + int bytesRead; + + while ((bytesRead = br.read(contents)) != -1) + { + fileContent.append(new String(contents, 0, bytesRead)); + // fileContent.append("Hallo "); + } + + // System.out.println("Body: \n\n\n\n\n"+body+"\n\n\n\n"+"Länge: "+body.length()+"\n\n"); + request.setFile("file", fileContent.toString().getBytes(), + file.getName(), "image/jpeg", "binary"); + + String response = request.performRequest(); + // String response = request.performRequest("TEST TEST"); + System.out.println("nach dem Hochladen" + response); + Toast.makeText(this, R.string.publish, Toast.LENGTH_SHORT); + + } catch (IOException e) + { + e.printStackTrace(); + throw new RuntimeException(e); + } + } + } + } + } + + public String getPath(Uri uri) + { + String[] projection = { MediaStore.Images.Media.DATA }; + Cursor cursor = managedQuery(uri, projection, null, null, null); + int column_index = cursor + .getColumnIndexOrThrow(MediaStore.Images.Media.DATA); + cursor.moveToFirst(); + return cursor.getString(column_index); + } } diff --git a/src/de/openrat/android/blog/FolderEntry.java b/src/de/openrat/android/blog/FolderEntry.java @@ -0,0 +1,17 @@ +package de.openrat.android.blog; + + +public class FolderEntry +{ + public FType type; + public String id; + public String name; + public String description; + + + public enum FType + { + FOLDER, PAGE, FILE, LINK, PROJECT; + } + +} diff --git a/src/de/openrat/android/blog/OpenRatBlog.java b/src/de/openrat/android/blog/OpenRatBlog.java @@ -5,6 +5,7 @@ import java.io.IOException; import org.json.JSONObject; import android.app.Activity; +import android.app.ProgressDialog; import android.content.Intent; import android.content.SharedPreferences; import android.os.Bundle; @@ -46,7 +47,10 @@ public class OpenRatBlog extends Activity String response = null; try { + ProgressDialog dialog = ProgressDialog.show(OpenRatBlog.this,getResources().getString(R.string.loading),getResources().getString(R.string.waiting)); + response = request.performRequest(); + dialog.dismiss(); } catch (IOException e) { diff --git a/src/de/openrat/android/blog/ProjectActivity.java b/src/de/openrat/android/blog/ProjectActivity.java @@ -5,23 +5,23 @@ package de.openrat.android.blog; import java.io.IOException; import java.util.ArrayList; -import java.util.HashMap; import java.util.List; -import java.util.Map; import org.json.JSONArray; import org.json.JSONObject; import android.app.ListActivity; +import android.app.ProgressDialog; import android.content.Intent; import android.os.Bundle; import android.view.View; import android.widget.AdapterView; import android.widget.ListAdapter; import android.widget.ListView; -import android.widget.SimpleAdapter; import android.widget.Toast; import android.widget.AdapterView.OnItemClickListener; +import de.openrat.android.blog.FolderEntry.FType; +import de.openrat.android.blog.adapter.FolderContentAdapter; import de.openrat.android.blog.client.CMSRequest; /** @@ -35,7 +35,7 @@ public class ProjectActivity extends ListActivity private static final String NAME = "name"; private static final String DESCRIPTION = "description"; private CMSRequest request; - private List<Map<String, String>> data; + private List<FolderEntry> data; @Override protected void onCreate(Bundle savedInstanceState) @@ -49,7 +49,7 @@ public class ProjectActivity extends ListActivity ; String[] from = new String[] { NAME, DESCRIPTION }; ; - data = new ArrayList<Map<String, String>>(); + data = new ArrayList<FolderEntry>(); request = (CMSRequest) getIntent().getSerializableExtra(CLIENT); @@ -73,12 +73,15 @@ public class ProjectActivity extends ListActivity JSONArray projects = json.getJSONArray("projects"); for (int i = 0; i < projects.length(); i++) { - final Map<String, String> values = new HashMap<String, String>(); JSONObject project = projects.getJSONObject(i); - values.put(NAME, project.getString("name")); - values.put(DESCRIPTION, ""); - values.put(ID2, project.getString("id")); - data.add(values); + + final FolderEntry entry = new FolderEntry(); + entry.type = FType.PROJECT; + entry.name = project.getString("name"); + entry.description = ""; + entry.id = project.getString("id"); + + data.add(entry); } @@ -96,15 +99,12 @@ public class ProjectActivity extends ListActivity public void onItemClick(AdapterView<?> parent, View view, int position, long id) { - Toast.makeText(ProjectActivity.this, "Click on " + position, - Toast.LENGTH_SHORT).show(); - final Intent i = new Intent(ProjectActivity.this, FolderActivity.class); i.putExtra(CLIENT, request); // Projekt auswählen - String projectid = data.get(position).get(ID2); + String projectid = data.get(position).id; request = (CMSRequest) getIntent().getSerializableExtra(CLIENT); @@ -115,12 +115,20 @@ public class ProjectActivity extends ListActivity String response = null; try { + ProgressDialog dialog = ProgressDialog.show( + ProjectActivity.this, getResources().getString( + R.string.loading), getResources() + .getString(R.string.waiting)); + dialog.show(); response = request.performRequest(); - System.out.println("Projekt ausgewählt: " + response); + dialog.dismiss(); } catch (IOException e) { - System.err.println("Fehler bei Projektauswahl: "+response); + Toast.makeText(ProjectActivity.this, e.getMessage(), + Toast.LENGTH_LONG); + System.err + .println("Fehler bei Projektauswahl: " + response); System.err.println(e.getMessage()); } @@ -128,8 +136,7 @@ public class ProjectActivity extends ListActivity } }); - final ListAdapter adapter = new SimpleAdapter(this, data, - R.layout.listing_entry, from, to); + final ListAdapter adapter = new FolderContentAdapter(this, data); setListAdapter(adapter); } } diff --git a/src/de/openrat/android/blog/adapter/FSimpleAdapter.java b/src/de/openrat/android/blog/adapter/FSimpleAdapter.java @@ -1,27 +0,0 @@ -/** - * - */ -package de.openrat.android.blog.adapter; - -import java.util.List; -import java.util.Map; - -import android.content.Context; -import android.widget.SimpleAdapter; - -/** - * @author dankert - * - */ -public class FSimpleAdapter extends SimpleAdapter -{ - - public FSimpleAdapter(Context context, List<? extends Map<String, ?>> data, - int resource, String[] from, int[] to) - { - super(context, data, resource, from, to); - } - - - -} diff --git a/src/de/openrat/android/blog/adapter/FolderContentAdapter.java b/src/de/openrat/android/blog/adapter/FolderContentAdapter.java @@ -0,0 +1,104 @@ +/** + * + */ +package de.openrat.android.blog.adapter; + +import java.util.ArrayList; +import java.util.List; + +import android.content.Context; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.BaseAdapter; +import android.widget.ImageView; +import android.widget.TextView; +import de.openrat.android.blog.FolderEntry; +import de.openrat.android.blog.R; + +/** + * @author dankert + * + */ +public class FolderContentAdapter extends BaseAdapter +{ + + /** Remember our context so we can use it when constructing views. */ + private Context mContext; + + /** + * Hold onto a copy of the entire Contact List. + */ + private List<FolderEntry> data = new ArrayList<FolderEntry>(); + + private LayoutInflater inflator; + + public FolderContentAdapter(Context context, List<FolderEntry> data2) + { + mContext = context; + inflator = (LayoutInflater) context + .getSystemService(Context.LAYOUT_INFLATER_SERVICE); + data = data2; + } + + public int getCount() + { + return data.size(); + } + + public Object getItem(int position) + { + return data.get(position); + } + + /** Use the array index as a unique id. */ + public long getItemId(int position) + { + return position; + + } + + /** + * @param convertView + * The old view to overwrite, if one is passed + * @returns a ContactEntryView that holds wraps around an ContactEntry + */ + public View getView(int position, View convertView, ViewGroup parent) + { + + FolderEntry e = data.get(position); + + final View view = inflator.inflate(R.layout.listing_entry, null); + + ImageView image = (ImageView) view.findViewById(R.id.listentry_image); + switch (e.type) + { + case FOLDER: + image.setImageResource(R.drawable.icon_folder); + break; + case FILE: + image.setImageResource(R.drawable.icon_file); + break; + case PAGE: + image.setImageResource(R.drawable.icon_page); + break; + case LINK: + image.setImageResource(R.drawable.icon_link); + break; + case PROJECT: + image.setImageResource(R.drawable.icon_project); + break; + default: + } + + TextView name = (TextView) view.findViewById(R.id.listentry_name); + name.setText(e.name); + + TextView desc = (TextView) view + .findViewById(R.id.listentry_description); + desc.setText(e.description); + + return view; + } + +} diff --git a/src/de/openrat/android/blog/client/CMSRequest.java b/src/de/openrat/android/blog/client/CMSRequest.java @@ -20,378 +20,93 @@ 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.Serializable; -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> + * 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. + * 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 implements Serializable { - - // 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; +public class CMSRequest extends HTTPRequest implements Serializable +{ - private String cookieName; - private String cookieValue; - private String language; - - - /** - * - */ - public CMSRequest() + /** + * + */ + public CMSRequest() { - super(); - this.language = Locale.getDefault().getLanguage(); + super(); } - public String getLanguage() + /** + * @param host + * @param path + * @param port + */ + public CMSRequest(String host, String path, int port) { - return language; + super(host, path, port); } - public void setLanguage(String language) + /** + * @param host + * @param path + */ + public CMSRequest(String host, String path) { - this.language = language; + super(host, path); } /** - * 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()) { + * @param host + */ + public CMSRequest(String host) + { + super(host); + } - response.append(bufferedReader.readLine() + "\n"); - } - socket.close(); + /** + * Setzt die Action. + * + * @param actionName + */ + public void setAction(String actionName) + { + super.setParameter("action", actionName); + } - if (this.trace) - System.out.println("--- response body ---"); - if (this.trace) - System.out.println(response + "\n\n\n"); + /** + * Setzt die Action-Methode. + * + * @param methodName + */ + public void setActionMethod(String methodName) + { + super.setParameter("subaction", methodName); + } - return response.toString(); - } - finally { - try { - socket.close(); // Clean up the socket. - } - catch (IOException e) { - // We have done our very best. - } - } - } } diff --git a/src/de/openrat/android/blog/client/HTTPRequest.java b/src/de/openrat/android/blog/client/HTTPRequest.java @@ -0,0 +1,588 @@ +/* +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.Serializable; +import java.io.UnsupportedEncodingException; +import java.net.InetSocketAddress; +import java.net.Socket; +import java.net.SocketAddress; +import java.net.URLEncoder; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Locale; +import java.util.Map; +import java.util.Map.Entry; + +/** + * 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 HTTPRequest implements Serializable +{ + + private static final String CRLF = "\r\n"; + + private Multipart multipart = new Multipart(); + + // 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 Map<String, String> requestHeader = 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 HTTPRequest() + { + 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(); + requestHeader.clear(); + multipart.parts.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); + } + + /** + * + * 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 setHeader(String paramName, String paramValue) + { + + if (paramName == null || paramValue == null || "" == paramName) + throw new IllegalArgumentException( + "parameter name and value must have values"); + + requestHeader.put(paramName, paramValue); + } + + /** + * Constructs a CMS-Request to the specified server.<br> + * Server-Path is "/", Server-Port is 80. + * + * @param host + * hostname + */ + public HTTPRequest(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 HTTPRequest(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 HTTPRequest(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 + { + return performRequest(null); + } + + /** + * 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(String body) 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) + || (body != null || multipart.parts.size() > 0)) + 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"+CRLF); + + // Setting the HTTP Header + Map<String, String> headers = new HashMap<String, String>(); + headers.put("Host", this.serverHost); + headers.put("User-Agent", + "Mozilla/5.0; compatible (OpenRat android-client)"); + headers.put("Accept", "application/json"); + headers.put("Accept-Language", language); + headers.put("Accept-Charset", "utf-8"); + headers.put("Connection", "close"); + if (useCookie) + headers.put("Cookie", cookieName + "=" + cookieValue); + + if (HTTP_POST.equals(this.method)) + { + if (body == null && multipart.parts.size() == 0) + { + headers.put("Content-Type", + "application/x-www-form-urlencoded"); + headers.put("Content-Length", "" + parameterList.length()); + } else if (multipart.parts.size() > 0) + { + + headers.put("Content-Type", multipart.getContentType()); + headers.put("Content-Length", ""+multipart.getPayload().getBytes().length); + + + } else + { + headers.put("Content-Type", "text/plain"); + + } + } + + headers.putAll(requestHeader); + for (String headerName : headers.keySet()) + { + header.append(headerName + ": " + headers.get(headerName) + + CRLF); + + } + + header.append(CRLF); + + if (HTTP_POST.equals(this.method)) + { + if (body == null && multipart.parts.size() == 0) + header.append(parameterList); + else if (multipart.parts.size() > 0) + header.append(multipart.getPayload()); + else + header.append(body); + } + + 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. + } + } + + } + + public void setFile(String name, byte[] value, String filename, + String type, String encoding) + { + + Part part = new Part(); + part.file = value; + part.filename = filename; + part.encoding = encoding; + part.name = name; + part.contentType = type; + this.multipart.parts.add(part); + } + + public void setText(String name, String value) + { + + Part part = new Part(); + part.name = name; + part.text = value; + part.contentType = "text/plain"; + this.multipart.parts.add(part); + } + + private class Multipart implements Serializable + { + + private static final String CRLF = "\r\n"; + private static final String BOUNDARY = "614BA262123F3B29656A745C5DD26"; + List<Part> parts = new ArrayList<Part>(); + + public String getPayload() + { + StringBuffer body = new StringBuffer(); + + for (Part part : parts) + { + body.append("--" + BOUNDARY + CRLF); + body.append("Content-Type: " + part.contentType + CRLF); + + if (part.encoding != null) + body.append("Content-Transfer-Encoding: " + part.encoding + + CRLF); + + body.append("Content-Disposition: form-data; name=\"" + + part.name + + "\"" + + (part.filename != null ? ("; filename=\"" + + part.filename + "\"") : "") + CRLF); + body.append(CRLF); + if (part.file.length > 0) + body.append(new String(part.file)); + else + body.append(part.text); + body.append(CRLF); + } + body.append("--" + BOUNDARY + "--"); + return body.toString(); + } + + public String getContentType() + { + return "multipart/form-data; boundary=" + Multipart.BOUNDARY; + } + } + + private class Part implements Serializable + { + public byte[] file; + public String filename; + public String text; + public String name; + public String contentType; + public String encoding; + } +}