diff src/com/five_ten_sg/connectbot/HostEditorActivity.java @ 0:0ce5cc452d02

initial version
author Carl Byington <carl@five-ten-sg.com>
date Thu, 22 May 2014 10:41:19 -0700
parents
children 4ccfde0bc506
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/com/five_ten_sg/connectbot/HostEditorActivity.java	Thu May 22 10:41:19 2014 -0700
@@ -0,0 +1,426 @@
+/*
+ * ConnectBot: simple, powerful, open-source SSH client for Android
+ * Copyright 2007 Kenny Root, Jeffrey Sharkey
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.five_ten_sg.connectbot;
+
+import java.nio.charset.Charset;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Set;
+
+import com.five_ten_sg.connectbot.bean.HostBean;
+import com.five_ten_sg.connectbot.service.TerminalBridge;
+import com.five_ten_sg.connectbot.service.TerminalManager;
+import com.five_ten_sg.connectbot.util.HostDatabase;
+import com.five_ten_sg.connectbot.util.PubkeyDatabase;
+import android.content.ComponentName;
+import android.content.ContentValues;
+import android.content.Context;
+import android.content.Intent;
+import android.content.ServiceConnection;
+import android.content.SharedPreferences;
+import android.content.SharedPreferences.OnSharedPreferenceChangeListener;
+import android.database.Cursor;
+import android.database.sqlite.SQLiteDatabase;
+import android.os.Bundle;
+import android.os.IBinder;
+import android.preference.CheckBoxPreference;
+import android.preference.ListPreference;
+import android.preference.Preference;
+import android.preference.PreferenceActivity;
+import android.util.Log;
+
+public class HostEditorActivity extends PreferenceActivity implements OnSharedPreferenceChangeListener {
+    public class CursorPreferenceHack implements SharedPreferences {
+        protected final String table;
+        protected final long id;
+
+        protected Map<String, String> values = new HashMap<String, String>();
+//      protected Map<String, String> pubkeys = new HashMap<String, String>();
+
+        public CursorPreferenceHack(String table, long id) {
+            this.table = table;
+            this.id = id;
+            cacheValues();
+        }
+
+        protected final void cacheValues() {
+            // fill a cursor and cache the values locally
+            // this makes sure we dont have any floating cursor to dispose later
+            SQLiteDatabase db = hostdb.getReadableDatabase();
+            Cursor cursor = db.query(table, null, "_id = ?",
+                                     new String[] { String.valueOf(id) }, null, null, null);
+
+            if (cursor.moveToFirst()) {
+                for (int i = 0; i < cursor.getColumnCount(); i++) {
+                    String key = cursor.getColumnName(i);
+
+                    if (key.equals(HostDatabase.FIELD_HOST_HOSTKEY)) continue;
+
+                    String value = cursor.getString(i);
+                    values.put(key, value);
+                }
+            }
+
+            cursor.close();
+            db.close();
+//          db = pubkeydb.getReadableDatabase();
+//          cursor = db.query(PubkeyDatabase.TABLE_PUBKEYS,
+//                  new String[] { "_id", PubkeyDatabase.FIELD_PUBKEY_NICKNAME },
+//                  null, null, null, null, null);
+//
+//          if (cursor.moveToFirst()) {
+//              do {
+//                  String pubkeyid = String.valueOf(cursor.getLong(0));
+//                  String value = cursor.getString(1);
+//                  pubkeys.put(pubkeyid, value);
+//              } while (cursor.moveToNext());
+//          }
+//
+//          cursor.close();
+//          db.close();
+        }
+
+        public boolean contains(String key) {
+            return values.containsKey(key);
+        }
+
+        public class Editor implements SharedPreferences.Editor {
+
+            private ContentValues update = new ContentValues();
+
+            public SharedPreferences.Editor clear() {
+                Log.d(this.getClass().toString(), "clear()");
+                update = new ContentValues();
+                return this;
+            }
+
+            public boolean commit() {
+                //Log.d(this.getClass().toString(), "commit() changes back to database");
+                SQLiteDatabase db = hostdb.getWritableDatabase();
+                db.update(table, update, "_id = ?", new String[] { String.valueOf(id) });
+                db.close();
+                // make sure we refresh the parent cached values
+                cacheValues();
+
+                // and update any listeners
+                for (OnSharedPreferenceChangeListener listener : listeners) {
+                    listener.onSharedPreferenceChanged(CursorPreferenceHack.this, null);
+                }
+
+                return true;
+            }
+
+            // Gingerbread compatibility
+            public void apply() {
+                commit();
+            }
+
+            public android.content.SharedPreferences.Editor putBoolean(String key, boolean value) {
+                return this.putString(key, Boolean.toString(value));
+            }
+
+            public android.content.SharedPreferences.Editor putFloat(String key, float value) {
+                return this.putString(key, Float.toString(value));
+            }
+
+            public android.content.SharedPreferences.Editor putInt(String key, int value) {
+                return this.putString(key, Integer.toString(value));
+            }
+
+            public android.content.SharedPreferences.Editor putLong(String key, long value) {
+                return this.putString(key, Long.toString(value));
+            }
+
+            public android.content.SharedPreferences.Editor putString(String key, String value) {
+                //Log.d(this.getClass().toString(), String.format("Editor.putString(key=%s, value=%s)", key, value));
+                update.put(key, value);
+                return this;
+            }
+
+            public android.content.SharedPreferences.Editor remove(String key) {
+                //Log.d(this.getClass().toString(), String.format("Editor.remove(key=%s)", key));
+                update.remove(key);
+                return this;
+            }
+
+            public android.content.SharedPreferences.Editor putStringSet(String key, Set<String> value) {
+                throw new UnsupportedOperationException("HostEditor Prefs do not support Set<String>");
+            }
+        }
+
+
+        public Editor edit() {
+            //Log.d(this.getClass().toString(), "edit()");
+            return new Editor();
+        }
+
+        public Map<String, ?> getAll() {
+            return values;
+        }
+
+        public boolean getBoolean(String key, boolean defValue) {
+            return Boolean.valueOf(this.getString(key, Boolean.toString(defValue)));
+        }
+
+        public float getFloat(String key, float defValue) {
+            return Float.valueOf(this.getString(key, Float.toString(defValue)));
+        }
+
+        public int getInt(String key, int defValue) {
+            return Integer.valueOf(this.getString(key, Integer.toString(defValue)));
+        }
+
+        public long getLong(String key, long defValue) {
+            return Long.valueOf(this.getString(key, Long.toString(defValue)));
+        }
+
+        public String getString(String key, String defValue) {
+            //Log.d(this.getClass().toString(), String.format("getString(key=%s, defValue=%s)", key, defValue));
+            if (!values.containsKey(key)) return defValue;
+
+            return values.get(key);
+        }
+
+        public Set<String> getStringSet(String key, Set<String> defValue) {
+            throw new ClassCastException("HostEditor Prefs do not support Set<String>");
+        }
+
+        protected List<OnSharedPreferenceChangeListener> listeners = new LinkedList<OnSharedPreferenceChangeListener>();
+
+        public void registerOnSharedPreferenceChangeListener(OnSharedPreferenceChangeListener listener) {
+            listeners.add(listener);
+        }
+
+        public void unregisterOnSharedPreferenceChangeListener(OnSharedPreferenceChangeListener listener) {
+            listeners.remove(listener);
+        }
+
+    }
+
+    @Override
+    public SharedPreferences getSharedPreferences(String name, int mode) {
+        //Log.d(this.getClass().toString(), String.format("getSharedPreferences(name=%s)", name));
+        return this.pref;
+    }
+
+    protected static final String TAG = "ConnectBot.HostEditorActivity";
+
+    protected HostDatabase hostdb = null;
+    private PubkeyDatabase pubkeydb = null;
+
+    private CursorPreferenceHack pref;
+    private ServiceConnection connection;
+
+    private HostBean host;
+    protected TerminalBridge hostBridge;
+
+    @Override
+    public void onCreate(Bundle icicle) {
+        super.onCreate(icicle);
+        long hostId = this.getIntent().getLongExtra(Intent.EXTRA_TITLE, -1);
+        // TODO: we could pass through a specific ContentProvider uri here
+        //this.getPreferenceManager().setSharedPreferencesName(uri);
+        this.hostdb = new HostDatabase(this);
+        this.pubkeydb = new PubkeyDatabase(this);
+        host = hostdb.findHostById(hostId);
+        connection = new ServiceConnection() {
+            public void onServiceConnected(ComponentName className, IBinder service) {
+                TerminalManager bound = ((TerminalManager.TerminalBinder) service).getService();
+                hostBridge = bound.getConnectedBridge(host);
+            }
+            public void onServiceDisconnected(ComponentName name) {
+                hostBridge = null;
+            }
+        };
+        this.pref = new CursorPreferenceHack(HostDatabase.TABLE_HOSTS, hostId);
+        this.pref.registerOnSharedPreferenceChangeListener(this);
+        this.addPreferencesFromResource(R.xml.host_prefs);
+        // add all existing pubkeys to our listpreference for user to choose from
+        // TODO: may be an issue here when this activity is recycled after adding a new pubkey
+        // TODO: should consider moving into onStart, but we dont have a good way of resetting the listpref after filling once
+        ListPreference pubkeyPref = (ListPreference)this.findPreference(HostDatabase.FIELD_HOST_PUBKEYID);
+        List<CharSequence> pubkeyNicks = new LinkedList<CharSequence> (Arrays.asList(pubkeyPref.getEntries()));
+        pubkeyNicks.addAll(pubkeydb.allValues(PubkeyDatabase.FIELD_PUBKEY_NICKNAME));
+        pubkeyPref.setEntries(pubkeyNicks.toArray(new CharSequence[pubkeyNicks.size()]));
+        List<CharSequence> pubkeyIds = new LinkedList<CharSequence> (Arrays.asList(pubkeyPref.getEntryValues()));
+        pubkeyIds.addAll(pubkeydb.allValues("_id"));
+        pubkeyPref.setEntryValues(pubkeyIds.toArray(new CharSequence[pubkeyIds.size()]));
+        // Populate the character set encoding list with all available
+        final ListPreference charsetPref = (ListPreference) findPreference(HostDatabase.FIELD_HOST_ENCODING);
+
+        if (CharsetHolder.isInitialized()) {
+            initCharsetPref(charsetPref);
+        }
+        else {
+            String[] currentCharsetPref = new String[1];
+            currentCharsetPref[0] = charsetPref.getValue();
+            charsetPref.setEntryValues(currentCharsetPref);
+            charsetPref.setEntries(currentCharsetPref);
+            new Thread(new Runnable() {
+                public void run() {
+                    initCharsetPref(charsetPref);
+                }
+            }).start();
+        }
+
+        this.updateSummaries();
+    }
+
+    @Override
+    public void onStart() {
+        super.onStart();
+        bindService(new Intent(this, TerminalManager.class), connection, Context.BIND_AUTO_CREATE);
+
+        if (this.hostdb == null)
+            this.hostdb = new HostDatabase(this);
+
+        if (this.pubkeydb == null)
+            this.pubkeydb = new PubkeyDatabase(this);
+    }
+
+    @Override
+    public void onStop() {
+        super.onStop();
+        unbindService(connection);
+
+        if (this.hostdb != null) {
+            this.hostdb.close();
+            this.hostdb = null;
+        }
+
+        if (this.pubkeydb != null) {
+            this.pubkeydb.close();
+            this.pubkeydb = null;
+        }
+    }
+
+    private void updateSummaries() {
+        // for all text preferences, set hint as current database value
+        for (String key : this.pref.values.keySet()) {
+            if (key.equals(HostDatabase.FIELD_HOST_POSTLOGIN)) continue;
+
+            Preference pref = this.findPreference(key);
+
+            if (pref == null) continue;
+
+            if (pref instanceof CheckBoxPreference) continue;
+
+            CharSequence value = this.pref.getString(key, "");
+
+            if (key.equals(HostDatabase.FIELD_HOST_PUBKEYID)) {
+                try {
+                    int pubkeyId = Integer.parseInt((String) value);
+
+                    if (pubkeyId >= 0)
+                        pref.setSummary(pubkeydb.getNickname(pubkeyId));
+                    else if (pubkeyId == HostDatabase.PUBKEYID_ANY)
+                        pref.setSummary(R.string.list_pubkeyids_any);
+                    else if (pubkeyId == HostDatabase.PUBKEYID_NEVER)
+                        pref.setSummary(R.string.list_pubkeyids_none);
+
+                    continue;
+                }
+                catch (NumberFormatException nfe) {
+                    // Fall through.
+                }
+            }
+            else if (pref instanceof ListPreference) {
+                ListPreference listPref = (ListPreference) pref;
+                int entryIndex = listPref.findIndexOfValue((String) value);
+
+                if (entryIndex >= 0)
+                    value = listPref.getEntries()[entryIndex];
+            }
+
+            pref.setSummary(value);
+        }
+    }
+
+    private void initCharsetPref(final ListPreference charsetPref) {
+        charsetPref.setEntryValues(CharsetHolder.getCharsetIds());
+        charsetPref.setEntries(CharsetHolder.getCharsetNames());
+    }
+
+    public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
+        // update values on changed preference
+        this.updateSummaries();
+
+        // Our CursorPreferenceHack always send null keys, so try to set charset anyway
+        if (hostBridge != null)
+            hostBridge.setCharset(sharedPreferences
+                                  .getString(HostDatabase.FIELD_HOST_ENCODING, HostDatabase.ENCODING_DEFAULT));
+    }
+
+    public static class CharsetHolder {
+        private static boolean initialized = false;
+
+        private static CharSequence[] charsetIds;
+        private static CharSequence[] charsetNames;
+
+        public static CharSequence[] getCharsetNames() {
+            if (charsetNames == null)
+                initialize();
+
+            return charsetNames;
+        }
+
+        public static CharSequence[] getCharsetIds() {
+            if (charsetIds == null)
+                initialize();
+
+            return charsetIds;
+        }
+
+        private synchronized static void initialize() {
+            if (initialized)
+                return;
+
+            List<CharSequence> charsetIdsList = new LinkedList<CharSequence>();
+            List<CharSequence> charsetNamesList = new LinkedList<CharSequence>();
+
+            for (Entry<String, Charset> entry : Charset.availableCharsets().entrySet()) {
+                Charset c = entry.getValue();
+
+                if (c.canEncode() && c.isRegistered()) {
+                    String key = entry.getKey();
+
+                    if (key.startsWith("cp")) {
+                        // Custom CP437 charset changes
+                        charsetIdsList.add("CP437");
+                        charsetNamesList.add("CP437");
+                    }
+
+                    charsetIdsList.add(entry.getKey());
+                    charsetNamesList.add(c.displayName());
+                }
+            }
+
+            charsetIds = charsetIdsList.toArray(new CharSequence[charsetIdsList.size()]);
+            charsetNames = charsetNamesList.toArray(new CharSequence[charsetNamesList.size()]);
+            initialized = true;
+        }
+
+        public static boolean isInitialized() {
+            return initialized;
+        }
+    }
+}