OSDN Git Service

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