comparison 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
comparison
equal deleted inserted replaced
-1:000000000000 0:0ce5cc452d02
1 /*
2 * ConnectBot: simple, powerful, open-source SSH client for Android
3 * Copyright 2007 Kenny Root, Jeffrey Sharkey
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17
18 package com.five_ten_sg.connectbot;
19
20 import java.nio.charset.Charset;
21 import java.util.Arrays;
22 import java.util.HashMap;
23 import java.util.LinkedList;
24 import java.util.List;
25 import java.util.Map;
26 import java.util.Map.Entry;
27 import java.util.Set;
28
29 import com.five_ten_sg.connectbot.bean.HostBean;
30 import com.five_ten_sg.connectbot.service.TerminalBridge;
31 import com.five_ten_sg.connectbot.service.TerminalManager;
32 import com.five_ten_sg.connectbot.util.HostDatabase;
33 import com.five_ten_sg.connectbot.util.PubkeyDatabase;
34 import android.content.ComponentName;
35 import android.content.ContentValues;
36 import android.content.Context;
37 import android.content.Intent;
38 import android.content.ServiceConnection;
39 import android.content.SharedPreferences;
40 import android.content.SharedPreferences.OnSharedPreferenceChangeListener;
41 import android.database.Cursor;
42 import android.database.sqlite.SQLiteDatabase;
43 import android.os.Bundle;
44 import android.os.IBinder;
45 import android.preference.CheckBoxPreference;
46 import android.preference.ListPreference;
47 import android.preference.Preference;
48 import android.preference.PreferenceActivity;
49 import android.util.Log;
50
51 public class HostEditorActivity extends PreferenceActivity implements OnSharedPreferenceChangeListener {
52 public class CursorPreferenceHack implements SharedPreferences {
53 protected final String table;
54 protected final long id;
55
56 protected Map<String, String> values = new HashMap<String, String>();
57 // protected Map<String, String> pubkeys = new HashMap<String, String>();
58
59 public CursorPreferenceHack(String table, long id) {
60 this.table = table;
61 this.id = id;
62 cacheValues();
63 }
64
65 protected final void cacheValues() {
66 // fill a cursor and cache the values locally
67 // this makes sure we dont have any floating cursor to dispose later
68 SQLiteDatabase db = hostdb.getReadableDatabase();
69 Cursor cursor = db.query(table, null, "_id = ?",
70 new String[] { String.valueOf(id) }, null, null, null);
71
72 if (cursor.moveToFirst()) {
73 for (int i = 0; i < cursor.getColumnCount(); i++) {
74 String key = cursor.getColumnName(i);
75
76 if (key.equals(HostDatabase.FIELD_HOST_HOSTKEY)) continue;
77
78 String value = cursor.getString(i);
79 values.put(key, value);
80 }
81 }
82
83 cursor.close();
84 db.close();
85 // db = pubkeydb.getReadableDatabase();
86 // cursor = db.query(PubkeyDatabase.TABLE_PUBKEYS,
87 // new String[] { "_id", PubkeyDatabase.FIELD_PUBKEY_NICKNAME },
88 // null, null, null, null, null);
89 //
90 // if (cursor.moveToFirst()) {
91 // do {
92 // String pubkeyid = String.valueOf(cursor.getLong(0));
93 // String value = cursor.getString(1);
94 // pubkeys.put(pubkeyid, value);
95 // } while (cursor.moveToNext());
96 // }
97 //
98 // cursor.close();
99 // db.close();
100 }
101
102 public boolean contains(String key) {
103 return values.containsKey(key);
104 }
105
106 public class Editor implements SharedPreferences.Editor {
107
108 private ContentValues update = new ContentValues();
109
110 public SharedPreferences.Editor clear() {
111 Log.d(this.getClass().toString(), "clear()");
112 update = new ContentValues();
113 return this;
114 }
115
116 public boolean commit() {
117 //Log.d(this.getClass().toString(), "commit() changes back to database");
118 SQLiteDatabase db = hostdb.getWritableDatabase();
119 db.update(table, update, "_id = ?", new String[] { String.valueOf(id) });
120 db.close();
121 // make sure we refresh the parent cached values
122 cacheValues();
123
124 // and update any listeners
125 for (OnSharedPreferenceChangeListener listener : listeners) {
126 listener.onSharedPreferenceChanged(CursorPreferenceHack.this, null);
127 }
128
129 return true;
130 }
131
132 // Gingerbread compatibility
133 public void apply() {
134 commit();
135 }
136
137 public android.content.SharedPreferences.Editor putBoolean(String key, boolean value) {
138 return this.putString(key, Boolean.toString(value));
139 }
140
141 public android.content.SharedPreferences.Editor putFloat(String key, float value) {
142 return this.putString(key, Float.toString(value));
143 }
144
145 public android.content.SharedPreferences.Editor putInt(String key, int value) {
146 return this.putString(key, Integer.toString(value));
147 }
148
149 public android.content.SharedPreferences.Editor putLong(String key, long value) {
150 return this.putString(key, Long.toString(value));
151 }
152
153 public android.content.SharedPreferences.Editor putString(String key, String value) {
154 //Log.d(this.getClass().toString(), String.format("Editor.putString(key=%s, value=%s)", key, value));
155 update.put(key, value);
156 return this;
157 }
158
159 public android.content.SharedPreferences.Editor remove(String key) {
160 //Log.d(this.getClass().toString(), String.format("Editor.remove(key=%s)", key));
161 update.remove(key);
162 return this;
163 }
164
165 public android.content.SharedPreferences.Editor putStringSet(String key, Set<String> value) {
166 throw new UnsupportedOperationException("HostEditor Prefs do not support Set<String>");
167 }
168 }
169
170
171 public Editor edit() {
172 //Log.d(this.getClass().toString(), "edit()");
173 return new Editor();
174 }
175
176 public Map<String, ?> getAll() {
177 return values;
178 }
179
180 public boolean getBoolean(String key, boolean defValue) {
181 return Boolean.valueOf(this.getString(key, Boolean.toString(defValue)));
182 }
183
184 public float getFloat(String key, float defValue) {
185 return Float.valueOf(this.getString(key, Float.toString(defValue)));
186 }
187
188 public int getInt(String key, int defValue) {
189 return Integer.valueOf(this.getString(key, Integer.toString(defValue)));
190 }
191
192 public long getLong(String key, long defValue) {
193 return Long.valueOf(this.getString(key, Long.toString(defValue)));
194 }
195
196 public String getString(String key, String defValue) {
197 //Log.d(this.getClass().toString(), String.format("getString(key=%s, defValue=%s)", key, defValue));
198 if (!values.containsKey(key)) return defValue;
199
200 return values.get(key);
201 }
202
203 public Set<String> getStringSet(String key, Set<String> defValue) {
204 throw new ClassCastException("HostEditor Prefs do not support Set<String>");
205 }
206
207 protected List<OnSharedPreferenceChangeListener> listeners = new LinkedList<OnSharedPreferenceChangeListener>();
208
209 public void registerOnSharedPreferenceChangeListener(OnSharedPreferenceChangeListener listener) {
210 listeners.add(listener);
211 }
212
213 public void unregisterOnSharedPreferenceChangeListener(OnSharedPreferenceChangeListener listener) {
214 listeners.remove(listener);
215 }
216
217 }
218
219 @Override
220 public SharedPreferences getSharedPreferences(String name, int mode) {
221 //Log.d(this.getClass().toString(), String.format("getSharedPreferences(name=%s)", name));
222 return this.pref;
223 }
224
225 protected static final String TAG = "ConnectBot.HostEditorActivity";
226
227 protected HostDatabase hostdb = null;
228 private PubkeyDatabase pubkeydb = null;
229
230 private CursorPreferenceHack pref;
231 private ServiceConnection connection;
232
233 private HostBean host;
234 protected TerminalBridge hostBridge;
235
236 @Override
237 public void onCreate(Bundle icicle) {
238 super.onCreate(icicle);
239 long hostId = this.getIntent().getLongExtra(Intent.EXTRA_TITLE, -1);
240 // TODO: we could pass through a specific ContentProvider uri here
241 //this.getPreferenceManager().setSharedPreferencesName(uri);
242 this.hostdb = new HostDatabase(this);
243 this.pubkeydb = new PubkeyDatabase(this);
244 host = hostdb.findHostById(hostId);
245 connection = new ServiceConnection() {
246 public void onServiceConnected(ComponentName className, IBinder service) {
247 TerminalManager bound = ((TerminalManager.TerminalBinder) service).getService();
248 hostBridge = bound.getConnectedBridge(host);
249 }
250 public void onServiceDisconnected(ComponentName name) {
251 hostBridge = null;
252 }
253 };
254 this.pref = new CursorPreferenceHack(HostDatabase.TABLE_HOSTS, hostId);
255 this.pref.registerOnSharedPreferenceChangeListener(this);
256 this.addPreferencesFromResource(R.xml.host_prefs);
257 // add all existing pubkeys to our listpreference for user to choose from
258 // TODO: may be an issue here when this activity is recycled after adding a new pubkey
259 // TODO: should consider moving into onStart, but we dont have a good way of resetting the listpref after filling once
260 ListPreference pubkeyPref = (ListPreference)this.findPreference(HostDatabase.FIELD_HOST_PUBKEYID);
261 List<CharSequence> pubkeyNicks = new LinkedList<CharSequence> (Arrays.asList(pubkeyPref.getEntries()));
262 pubkeyNicks.addAll(pubkeydb.allValues(PubkeyDatabase.FIELD_PUBKEY_NICKNAME));
263 pubkeyPref.setEntries(pubkeyNicks.toArray(new CharSequence[pubkeyNicks.size()]));
264 List<CharSequence> pubkeyIds = new LinkedList<CharSequence> (Arrays.asList(pubkeyPref.getEntryValues()));
265 pubkeyIds.addAll(pubkeydb.allValues("_id"));
266 pubkeyPref.setEntryValues(pubkeyIds.toArray(new CharSequence[pubkeyIds.size()]));
267 // Populate the character set encoding list with all available
268 final ListPreference charsetPref = (ListPreference) findPreference(HostDatabase.FIELD_HOST_ENCODING);
269
270 if (CharsetHolder.isInitialized()) {
271 initCharsetPref(charsetPref);
272 }
273 else {
274 String[] currentCharsetPref = new String[1];
275 currentCharsetPref[0] = charsetPref.getValue();
276 charsetPref.setEntryValues(currentCharsetPref);
277 charsetPref.setEntries(currentCharsetPref);
278 new Thread(new Runnable() {
279 public void run() {
280 initCharsetPref(charsetPref);
281 }
282 }).start();
283 }
284
285 this.updateSummaries();
286 }
287
288 @Override
289 public void onStart() {
290 super.onStart();
291 bindService(new Intent(this, TerminalManager.class), connection, Context.BIND_AUTO_CREATE);
292
293 if (this.hostdb == null)
294 this.hostdb = new HostDatabase(this);
295
296 if (this.pubkeydb == null)
297 this.pubkeydb = new PubkeyDatabase(this);
298 }
299
300 @Override
301 public void onStop() {
302 super.onStop();
303 unbindService(connection);
304
305 if (this.hostdb != null) {
306 this.hostdb.close();
307 this.hostdb = null;
308 }
309
310 if (this.pubkeydb != null) {
311 this.pubkeydb.close();
312 this.pubkeydb = null;
313 }
314 }
315
316 private void updateSummaries() {
317 // for all text preferences, set hint as current database value
318 for (String key : this.pref.values.keySet()) {
319 if (key.equals(HostDatabase.FIELD_HOST_POSTLOGIN)) continue;
320
321 Preference pref = this.findPreference(key);
322
323 if (pref == null) continue;
324
325 if (pref instanceof CheckBoxPreference) continue;
326
327 CharSequence value = this.pref.getString(key, "");
328
329 if (key.equals(HostDatabase.FIELD_HOST_PUBKEYID)) {
330 try {
331 int pubkeyId = Integer.parseInt((String) value);
332
333 if (pubkeyId >= 0)
334 pref.setSummary(pubkeydb.getNickname(pubkeyId));
335 else if (pubkeyId == HostDatabase.PUBKEYID_ANY)
336 pref.setSummary(R.string.list_pubkeyids_any);
337 else if (pubkeyId == HostDatabase.PUBKEYID_NEVER)
338 pref.setSummary(R.string.list_pubkeyids_none);
339
340 continue;
341 }
342 catch (NumberFormatException nfe) {
343 // Fall through.
344 }
345 }
346 else if (pref instanceof ListPreference) {
347 ListPreference listPref = (ListPreference) pref;
348 int entryIndex = listPref.findIndexOfValue((String) value);
349
350 if (entryIndex >= 0)
351 value = listPref.getEntries()[entryIndex];
352 }
353
354 pref.setSummary(value);
355 }
356 }
357
358 private void initCharsetPref(final ListPreference charsetPref) {
359 charsetPref.setEntryValues(CharsetHolder.getCharsetIds());
360 charsetPref.setEntries(CharsetHolder.getCharsetNames());
361 }
362
363 public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
364 // update values on changed preference
365 this.updateSummaries();
366
367 // Our CursorPreferenceHack always send null keys, so try to set charset anyway
368 if (hostBridge != null)
369 hostBridge.setCharset(sharedPreferences
370 .getString(HostDatabase.FIELD_HOST_ENCODING, HostDatabase.ENCODING_DEFAULT));
371 }
372
373 public static class CharsetHolder {
374 private static boolean initialized = false;
375
376 private static CharSequence[] charsetIds;
377 private static CharSequence[] charsetNames;
378
379 public static CharSequence[] getCharsetNames() {
380 if (charsetNames == null)
381 initialize();
382
383 return charsetNames;
384 }
385
386 public static CharSequence[] getCharsetIds() {
387 if (charsetIds == null)
388 initialize();
389
390 return charsetIds;
391 }
392
393 private synchronized static void initialize() {
394 if (initialized)
395 return;
396
397 List<CharSequence> charsetIdsList = new LinkedList<CharSequence>();
398 List<CharSequence> charsetNamesList = new LinkedList<CharSequence>();
399
400 for (Entry<String, Charset> entry : Charset.availableCharsets().entrySet()) {
401 Charset c = entry.getValue();
402
403 if (c.canEncode() && c.isRegistered()) {
404 String key = entry.getKey();
405
406 if (key.startsWith("cp")) {
407 // Custom CP437 charset changes
408 charsetIdsList.add("CP437");
409 charsetNamesList.add("CP437");
410 }
411
412 charsetIdsList.add(entry.getKey());
413 charsetNamesList.add(c.displayName());
414 }
415 }
416
417 charsetIds = charsetIdsList.toArray(new CharSequence[charsetIdsList.size()]);
418 charsetNames = charsetNamesList.toArray(new CharSequence[charsetNamesList.size()]);
419 initialized = true;
420 }
421
422 public static boolean isInitialized() {
423 return initialized;
424 }
425 }
426 }