OSDN Git Service

Merge pull request #9 from ygorigor/master
[android-x86/external-koush-Superuser.git] / Superuser / src / com / koushikdutta / superuser / util / Settings.java
1 package com.koushikdutta.superuser.util;
2
3 import java.io.ByteArrayOutputStream;
4 import java.io.DataInputStream;
5 import java.io.DataOutputStream;
6 import java.io.File;
7 import java.io.FileInputStream;
8 import java.io.FileOutputStream;
9 import java.io.IOException;
10 import java.io.InputStream;
11 import java.security.MessageDigest;
12
13 import android.content.ContentValues;
14 import android.content.Context;
15 import android.database.Cursor;
16 import android.database.sqlite.SQLiteDatabase;
17 import android.database.sqlite.SQLiteOpenHelper;
18 import android.os.Build;
19 import android.util.Base64;
20
21 import com.koushikdutta.superuser.Helper;
22
23 public class Settings {
24     SQLiteDatabase mDatabase;
25     Context mContext;
26
27     private Settings(Context context) {
28         mContext = context;
29         SQLiteOpenHelper helper = new SQLiteOpenHelper(mContext, "settings.db", null, 1) {
30             private final static String mDDL = "CREATE TABLE settings (key TEXT PRIMARY KEY, value TEXT);";
31
32             @Override
33             public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
34                 onCreate(db);
35             }
36
37             @Override
38             public void onCreate(SQLiteDatabase db) {
39                 db.execSQL(mDDL);
40             }
41         };
42         mDatabase = helper.getWritableDatabase();
43     }
44
45     private static Settings mInstance;
46
47     public static Settings getInstance(Context context) {
48         if (mInstance == null) {
49             mInstance = new Settings(context.getApplicationContext());
50         }
51         return mInstance;
52     }
53
54     public void setString(String name, String value) {
55         ContentValues cv = new ContentValues();
56         cv.put("key", name);
57         cv.put("value", value);
58         mDatabase.replace("settings", null, cv);
59     }
60
61     public String getString(String name) {
62         return getString(name, null);
63     }
64
65     public String getString(String name, String defaultValue) {
66         Cursor cursor = mDatabase.query("settings", new String[] { "value" }, "key='" + name + "'", null, null, null, null);
67         try {
68             if (cursor.moveToNext())
69                 return cursor.getString(0);
70         }
71         finally {
72             cursor.close();
73         }
74         return defaultValue;
75     }
76
77     public void setInt(String name, int value) {
78         setString(name, ((Integer) value).toString());
79     }
80
81     public int getInt(String name, int defaultValue) {
82         try {
83             return Integer.parseInt(getString(name, null));
84         }
85         catch (Exception ex) {
86             return defaultValue;
87         }
88     }
89
90     public void setLong(String name, long value) {
91         setString(name, ((Long) value).toString());
92     }
93
94     public long getLong(String name, long defaultValue) {
95         try {
96             return Long.parseLong(getString(name, null));
97         }
98         catch (Exception ex) {
99             return defaultValue;
100         }
101     }
102
103     public void setBoolean(String name, boolean value) {
104         setString(name, ((Boolean) value).toString());
105     }
106
107     public boolean getBoolean(String name, boolean defaultValue) {
108         try {
109             return Boolean.parseBoolean(getString(name, ((Boolean) defaultValue).toString()));
110         }
111         catch (Exception ex) {
112             ex.printStackTrace();
113             return defaultValue;
114         }
115     }
116     
117     private static final String KEY_LOGGING = "logging";
118     public static boolean getLogging(Context context) {
119         return getInstance(context).getBoolean(KEY_LOGGING, true);
120     }
121     
122     public static void setLogging(Context context, boolean logging) {
123         getInstance(context).setBoolean(KEY_LOGGING, logging);
124     }
125     
126     private static final String KEY_TIMEOUT = "timeout";
127     public static final int REQUEST_TIMEOUT_DEFAULT = 30;
128     public static int getRequestTimeout(Context context) {
129         return getInstance(context).getInt(KEY_TIMEOUT, REQUEST_TIMEOUT_DEFAULT);
130     }
131     
132     public static void setTimeout(Context context, int timeout) {
133         getInstance(context).setInt(KEY_TIMEOUT, timeout);
134     }
135
136     private static final String KEY_NOTIFICATION = "notification";
137     public static final int NOTIFICATION_TYPE_NONE = 0;
138     public static final int NOTIFICATION_TYPE_TOAST = 1;
139     public static final int NOTIFICATION_TYPE_NOTIFICATION = 2;
140     public static final int NOTIFICATION_TYPE_DEFAULT = NOTIFICATION_TYPE_TOAST;
141     public static int getNotificationType(Context context) {
142         switch (getInstance(context).getInt(KEY_NOTIFICATION, NOTIFICATION_TYPE_DEFAULT)) {
143         case NOTIFICATION_TYPE_NONE:
144             return NOTIFICATION_TYPE_NONE;
145         case NOTIFICATION_TYPE_NOTIFICATION:
146             return NOTIFICATION_TYPE_NOTIFICATION;
147         case NOTIFICATION_TYPE_TOAST:
148             return NOTIFICATION_TYPE_TOAST;
149         default:
150             return NOTIFICATION_TYPE_DEFAULT;
151         }
152     }
153     
154     public static void setNotificationType(Context context, int notification) {
155         getInstance(context).setInt(KEY_NOTIFICATION, notification);
156     }
157     
158     public static final String KEY_PIN = "pin";
159     public static final boolean isPinProtected(Context context) {
160         return Settings.getInstance(context).getString(KEY_PIN) != null;
161     }
162     
163     private static String digest(String value) {
164         // ok, there's honestly no point in digesting the pin.
165         // if someone gets a hold of the hash, there's really only like
166         // 10^n possible values to brute force, where N is generally
167         // 4. Ie, 10000. Yay, security theater. This really ought
168         // to be a password.
169         if (value == null || value.length() == 0)
170             return null;
171         try {
172             MessageDigest digester = MessageDigest.getInstance("MD5");
173             return Base64.encodeToString(digester.digest(value.getBytes()), Base64.DEFAULT);
174         }
175         catch (Exception e) {
176             return value;
177         }
178     }
179     
180     public static void setPin(Context context, String pin) {
181         Settings.getInstance(context).setString(KEY_PIN, digest(pin));
182     }
183     
184     public static boolean checkPin(Context context, String pin) {
185         pin = digest(pin);
186         String hashed = Settings.getInstance(context).getString(KEY_PIN);
187         if (pin == null)
188             return hashed == null || hashed.length() == 0;
189         return pin.equals(hashed);
190     }
191
192     private static final String KEY_REQUIRE_PREMISSION = "require_permission";
193     public static boolean getRequirePermission(Context context) {
194         return getInstance(context).getBoolean(KEY_REQUIRE_PREMISSION, false);
195     }
196     
197     public static void setRequirePermission(Context context, boolean require) {
198         getInstance(context).setBoolean(KEY_REQUIRE_PREMISSION, require);
199     }
200     
201     private static final String KEY_AUTOMATIC_RESPONSE = "automatic_response";
202     public static final int AUTOMATIC_RESPONSE_PROMPT = 0;
203     public static final int AUTOMATIC_RESPONSE_ALLOW = 1;
204     public static final int AUTOMATIC_RESPONSE_DENY = 2;
205     public static final int AUTOMATIC_RESPONSE_DEFAULT = AUTOMATIC_RESPONSE_PROMPT;
206     public static int getAutomaticResponse(Context context) {
207         switch (getInstance(context).getInt(KEY_AUTOMATIC_RESPONSE, AUTOMATIC_RESPONSE_DEFAULT)) {
208         case AUTOMATIC_RESPONSE_ALLOW:
209             return AUTOMATIC_RESPONSE_ALLOW;
210         case AUTOMATIC_RESPONSE_PROMPT:
211             return AUTOMATIC_RESPONSE_PROMPT;
212         case AUTOMATIC_RESPONSE_DENY:
213             return AUTOMATIC_RESPONSE_DENY;
214         default:
215             return AUTOMATIC_RESPONSE_DEFAULT;
216         }
217     }
218
219     public static void setAutomaticResponse(Context context, int response) {
220         getInstance(context).setInt(KEY_AUTOMATIC_RESPONSE, response);
221     }
222     
223     
224     static public String readFile(String filename) throws IOException {
225         return readFile(new File(filename));
226     }
227     
228     static public String readFile(File file) throws IOException {
229         byte[] buffer = new byte[(int) file.length()];
230         DataInputStream input = new DataInputStream(new FileInputStream(file));
231         input.readFully(buffer);
232         return new String(buffer);
233     }
234     
235     public static void writeFile(File file, String string) throws IOException {
236         writeFile(file.getAbsolutePath(), string);
237     }
238     
239     public static void writeFile(String file, String string) throws IOException {
240         File f = new File(file);
241         f.getParentFile().mkdirs();
242         DataOutputStream dout = new DataOutputStream(new FileOutputStream(f));
243         dout.write(string.getBytes());
244         dout.close();
245     }
246     
247     public static byte[] readToEndAsArray(InputStream input) throws IOException {
248         DataInputStream dis = new DataInputStream(input);
249         byte[] stuff = new byte[1024];
250         ByteArrayOutputStream buff = new ByteArrayOutputStream();
251         int read = 0;
252         while ((read = dis.read(stuff)) != -1)
253         {
254             buff.write(stuff, 0, read);
255         }
256         input.close();
257         return buff.toByteArray();
258     }
259
260     public static String readToEnd(InputStream input) throws IOException {
261         return new String(readToEndAsArray(input));
262     }
263
264     public static final int MULTIUSER_MODE_OWNER_ONLY = 0;
265     public static final int MULTIUSER_MODE_OWNER_MANAGED = 1;
266     public static final int MULTIUSER_MODE_USER = 2;
267     public static final int MULTIUSER_MODE_NONE = 3;
268     
269     private static final String MULTIUSER_VALUE_OWNER_ONLY  = "owner";
270     private static final String MULTIUSER_VALUE_OWNER_MANAGED = "managed";
271     private static final String MULTIUSER_VALUE_USER = "user";
272
273     public static final int getMultiuserMode(Context context) {
274         if (Build.VERSION.SDK_INT < 17)
275             return MULTIUSER_MODE_NONE;
276
277         if (!Helper.supportsMultipleUsers(context))
278             return MULTIUSER_MODE_NONE;
279         
280         try {
281             String mode;
282             if (Helper.isAdminUser(context)) {
283                 File file = context.getFileStreamPath("multiuser_mode");
284                 mode = readFile(file);
285             }
286             else {
287                 Process p = Runtime.getRuntime().exec("su -u");
288                 mode = readToEnd(p.getInputStream()).trim();
289             }
290             
291             if (MULTIUSER_VALUE_OWNER_MANAGED.equals(mode))
292                 return MULTIUSER_MODE_OWNER_MANAGED;
293             if (MULTIUSER_VALUE_USER.equals(mode))
294                 return MULTIUSER_MODE_USER;
295             if (MULTIUSER_VALUE_OWNER_ONLY.equals(mode))
296                 return MULTIUSER_MODE_OWNER_ONLY;
297         }
298         catch (Exception e) {
299         }
300         return MULTIUSER_MODE_OWNER_ONLY;
301     }
302     
303     public static void setMultiuserMode(Context context, int mode) {
304         if (!Helper.isAdminUser(context))
305             return;
306         try {
307             File file = context.getFileStreamPath("multiuser_mode");
308             switch (mode) {
309             case MULTIUSER_MODE_OWNER_MANAGED:
310                 writeFile(file, MULTIUSER_VALUE_OWNER_MANAGED);
311                 break;
312             case MULTIUSER_MODE_USER:
313                 writeFile(file, MULTIUSER_VALUE_USER);
314                 break;
315             case MULTIUSER_MODE_NONE:
316                 file.delete();
317                 break;
318             default:
319                 writeFile(file, MULTIUSER_VALUE_OWNER_ONLY);
320                 break;
321             }
322         }
323         catch (Exception ex) {
324         }
325     }
326 }