• R/O
  • HTTP
  • SSH
  • HTTPS

コミット

タグ
未設定

よく使われているワード(クリックで追加)

javac++androidlinuxc#windowsobjective-ccocoa誰得qtpythonphprubygameguibathyscaphec計画中(planning stage)翻訳omegatframeworktwitterdomtestvb.netdirectxゲームエンジンbtronarduinopreviewer

packages/apps/Superuser


コミットメタ情報

リビジョンe5940190f346347db7ec49f6e5e9c279cafeb78b (tree)
日時2010-08-23 08:31:32
作者ChainsDD <chainsdd@gmai...>
コミッターChainsDD

ログメッセージ

Download binaries instead of packaging them in the apk.

変更サマリ

差分

Binary files a/res/raw/su_2_3_1_bin_cd_signed.zip and /dev/null differ
Binary files a/res/raw/su_2_3_1_bin_ef_signed.zip and /dev/null differ
Binary files a/res/raw/su_cd and /dev/null differ
Binary files a/res/raw/su_ef and /dev/null differ
--- a/src/com/noshufou/android/su/Su.java
+++ b/src/com/noshufou/android/su/Su.java
@@ -1,44 +1,27 @@
11 package com.noshufou.android.su;
22
33 import java.io.BufferedReader;
4-import java.io.DataOutputStream;
5-import java.io.File;
6-import java.io.FileInputStream;
7-import java.io.FileNotFoundException;
8-import java.io.FileOutputStream;
94 import java.io.IOException;
10-import java.io.InputStream;
115 import java.io.InputStreamReader;
126
13-import android.app.AlertDialog;
147 import android.app.TabActivity;
15-import android.content.Context;
16-import android.content.DialogInterface;
178 import android.content.Intent;
189 import android.content.SharedPreferences;
1910 import android.content.pm.PackageManager;
2011 import android.content.pm.PackageManager.NameNotFoundException;
2112 import android.content.res.Resources;
22-import android.os.AsyncTask;
2313 import android.os.Bundle;
24-import android.os.Environment;
25-import android.os.Build.VERSION;
2614 import android.preference.PreferenceManager;
2715 import android.util.Log;
2816 import android.widget.TabHost;
29-import android.widget.Toast;
3017
3118 public class Su extends TabActivity {
3219 private static final String TAG = "Su";
3320
34- private Context mContext;
35-
3621 @Override
3722 protected void onCreate(Bundle savedInstanceState) {
3823 super.onCreate(savedInstanceState);
3924
40- mContext = this;
41-
4225 setContentView(R.layout.main);
4326
4427 Resources res = getResources();
@@ -88,38 +71,22 @@ public class Su extends TabActivity {
8871 }
8972 Log.d(TAG, "First run for version " + versionCode);
9073
91- copyNewFiles();
92-
9374 String suVer = getSuVersion();
94- String expectedSuVer = getString(R.string.expected_su_version) + ((versionCode < 5)?"-cd":"-ef");
95- Log.d(TAG, "Actual su version: " + suVer);
96- Log.d(TAG, "Expected su version: " + expectedSuVer);
97- if (suVer == null || !suVer.equals(expectedSuVer)) {
98- Log.d(TAG, "System has outdated su, attempting to copy new version");
99- new AlertDialog.Builder(mContext).setTitle(R.string.new_su)
100- .setMessage(R.string.new_su_msg)
101- .setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
102-
103- @Override
104- public void onClick(DialogInterface dialog, int which) {
105- new AutoUpdateTask().execute();
106- }
107- })
108- .setNegativeButton(android.R.string.cancel, null)
109- .create().show();
110- }
75+ Log.d(TAG, "su version: " + suVer);
76+ new Updater(this, suVer).doUpdate();
77+
11178 SharedPreferences.Editor editor = prefs.edit();
11279 editor.putInt("last_run", versionCode);
11380 editor.commit();
11481 }
11582
116- public static String getSuVersion()
83+ public static String getSuVersion()
11784 {
11885 Process process = null;
11986 try {
12087 process = Runtime.getRuntime().exec("su -v");
12188 BufferedReader stdInput = new BufferedReader(new InputStreamReader(process.getInputStream()));
122- String suVersion = stdInput.readLine();
89+ String suVersion = stdInput.readLine();
12390 stdInput.close();
12491 return suVersion;
12592 } catch (IOException e) {
@@ -127,148 +94,4 @@ public class Su extends TabActivity {
12794 return null;
12895 }
12996 }
130-
131- private void copyNewFiles() {
132- String[] files = fileList();
133- for (String s : files) {
134- deleteFile(s);
135- }
136- int sdkVersion = Integer.parseInt(VERSION.SDK);
137- InputStream fileInput = null;
138- FileOutputStream fileOutput = null;
139- int zipFile, binFile;
140- Log.d(TAG, "sdkVersion = " + sdkVersion);
141- if (sdkVersion < 5) {
142- Log.d(TAG, "Copying files for cupcake/donut");
143- zipFile = R.raw.su_2_3_1_bin_cd_signed;
144- binFile = R.raw.su_cd;
145- } else {
146- Log.d(TAG, "Copying files for eclair/froyo");
147- zipFile = R.raw.su_2_3_1_bin_ef_signed;
148- binFile = R.raw.su_ef;
149- }
150- try {
151- fileInput = getResources().openRawResource(zipFile);
152- byte[] zipReader = new byte[fileInput.available()];
153- while (fileInput.read(zipReader) != -1);
154- fileInput.close();
155- fileOutput = openFileOutput(getString(R.string.update_filename), MODE_WORLD_READABLE);
156- fileOutput.write(zipReader);
157- fileOutput.close();
158-
159- fileInput = getResources().openRawResource(binFile);
160- byte[] binReader = new byte[fileInput.available()];
161- while (fileInput.read(binReader) != -1);
162- fileInput.close();
163- fileOutput = openFileOutput("su", MODE_WORLD_READABLE);
164- fileOutput.write(binReader);
165- fileOutput.close();
166- } catch (IOException e) {
167- e.printStackTrace();
168- }
169-
170- }
171-
172- private void copyUpdateZip(boolean fromError) {
173- final String updateFilename = getString(R.string.update_filename);
174- if (fromError) {
175- new AlertDialog.Builder(mContext).setTitle(R.string.su_not_updated_title)
176- .setMessage(R.string.su_not_updated)
177- .setNeutralButton(android.R.string.ok, null)
178- .create().show();
179- }
180- File sdDir = new File(Environment.getExternalStorageDirectory().getPath());
181- if (sdDir.exists() && sdDir.canWrite()) {
182- File file = new File(sdDir.getAbsolutePath() + "/" + updateFilename);
183- try {
184- file.createNewFile();
185- } catch (IOException e) {
186- Log.e(TAG, "Couldn't create destination for " + updateFilename, e);
187- }
188- if (file.exists() && file.canWrite()) {
189- FileInputStream fileIn;
190- FileOutputStream fileOut;
191- try {
192- fileIn = openFileInput(updateFilename);
193- fileOut = new FileOutputStream(file);
194- byte[] reader = new byte[fileIn.available()];
195- while (fileIn.read(reader) != -1);
196- fileOut.write(reader);
197- if (fileIn != null) {
198- fileIn.close();
199- }
200- if (fileOut != null) {
201- fileOut.close();
202- }
203- } catch (FileNotFoundException e) {
204- Log.e(TAG, "Error:", e);
205- } catch (IOException e) {
206- Log.e(TAG, "Error:", e);
207- }
208- }
209- }
210- }
211-
212- public class AutoUpdateTask extends AsyncTask<String, Integer, Boolean> {
213-
214- @Override
215- protected Boolean doInBackground(String... params) {
216- String device = null;
217- boolean foundSystem = false;
218- try {
219- Process process = Runtime.getRuntime().exec("mount");
220- BufferedReader stdInput = new BufferedReader(new InputStreamReader(process.getInputStream()));
221- String line;
222- while ((line = stdInput.readLine()) != null) {
223- String[] array = line.split(" ");
224- device = array[0];
225- if ((array[1].equals("on") && array[2].equals("/system")) ||
226- array[1].equals("/system")) {
227- foundSystem = true;
228- break;
229- }
230- }
231- } catch (IOException e) {
232- Log.e(TAG, "Problem remounting /system", e);
233- return false;
234- }
235-
236- if (foundSystem && device != null) {
237- final String mountDev = device;
238- Process process;
239- try {
240- process = Runtime.getRuntime().exec("su");
241- DataOutputStream os = new DataOutputStream(process.getOutputStream());
242- os.writeBytes("mount -o remount,rw " + mountDev + " /system\n");
243- os.writeBytes("cat /data/data/com.noshufou.android.su/files/su > /system/bin/su\n");
244- os.writeBytes("chmod 06755 /system/bin/su\n");
245- os.writeBytes("mount -o remount,ro " + mountDev + " /system\n");
246- os.writeBytes("exit\n");
247- try {
248- process.waitFor();
249- if (process.exitValue() != 255) {
250- return true;
251- } else {
252- return false;
253- }
254- } catch (InterruptedException e) {
255- return false;
256- }
257- } catch (IOException e) {
258- return false;
259- }
260- }
261- return false;
262- }
263-
264- @Override
265- protected void onPostExecute(Boolean result) {
266- if (result) {
267- Toast.makeText(mContext, R.string.su_updated, Toast.LENGTH_SHORT).show();
268- } else {
269- copyUpdateZip(true);
270- }
271- }
272-
273- }
27497 }
--- /dev/null
+++ b/src/com/noshufou/android/su/Updater.java
@@ -0,0 +1,238 @@
1+package com.noshufou.android.su;
2+
3+import java.io.BufferedInputStream;
4+import java.io.BufferedReader;
5+import java.io.DataOutputStream;
6+import java.io.File;
7+import java.io.FileInputStream;
8+import java.io.FileNotFoundException;
9+import java.io.FileOutputStream;
10+import java.io.IOException;
11+import java.io.InputStreamReader;
12+import java.net.MalformedURLException;
13+import java.net.URL;
14+import java.net.URLConnection;
15+
16+import org.apache.http.util.ByteArrayBuffer;
17+import org.json.JSONException;
18+import org.json.JSONObject;
19+
20+import android.app.AlertDialog;
21+import android.content.Context;
22+import android.content.DialogInterface;
23+import android.os.AsyncTask;
24+import android.os.Environment;
25+import android.os.Build.VERSION;
26+import android.util.Log;
27+import android.widget.Toast;
28+
29+public class Updater {
30+ private static final String TAG = "Su.Updater";
31+
32+ private JSONObject mManifest;
33+ private JSONObject mBinaries;
34+ private Context mContext;
35+ private String mSuVersion;
36+
37+ public Updater(Context context, String suVersion) {
38+ mContext = context;
39+ mSuVersion = suVersion;
40+ }
41+
42+ public void doUpdate() {
43+ // Get the process started, it all goes from here.
44+ new DownloadFileTask().execute("http://dl.dropbox.com/u/6408470/Superuser/manifest.json");
45+ }
46+
47+ private void postManifest() {
48+ String expectedSuVersion = "";
49+ try {
50+ expectedSuVersion = mManifest.getString("version");
51+ int sdkVersion = Integer.parseInt(VERSION.SDK);
52+ if (sdkVersion < 5) {
53+ expectedSuVersion += "-cd";
54+ mBinaries = mManifest.getJSONObject("cd");
55+ } else {
56+ expectedSuVersion += "-ef";
57+ mBinaries = mManifest.getJSONObject("ef");
58+ }
59+ if (mSuVersion == null || !mSuVersion.equals(expectedSuVersion)) {
60+ Log.d(TAG, "System has outdated su, attempting to copy new version");
61+ new AlertDialog.Builder(mContext).setTitle(R.string.new_su)
62+ .setMessage(R.string.new_su_msg)
63+ .setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
64+
65+ @Override
66+ public void onClick(DialogInterface dialog, int which) {
67+ try {
68+ new DownloadFileTask()
69+ .execute(mBinaries.getString("binary"), mBinaries.getString("update"));
70+ } catch (JSONException e) {
71+ Log.e(TAG, "Malformed JSON", e);
72+ }
73+ }
74+ })
75+ .setNegativeButton(android.R.string.cancel, null)
76+ .create().show();
77+ } else {
78+ Toast.makeText(mContext, R.string.su_up_to_date, Toast.LENGTH_SHORT).show();
79+ }
80+ } catch (JSONException e) {
81+ Log.e(TAG, "Malformed JSON", e);
82+ return;
83+ }
84+ }
85+
86+ private void copyUpdateZip(boolean fromError) {
87+ final String updateFilename = mContext.getString(R.string.update_filename);
88+ if (fromError) {
89+ new AlertDialog.Builder(mContext).setTitle(R.string.su_not_updated_title)
90+ .setMessage(R.string.su_not_updated)
91+ .setNeutralButton(android.R.string.ok, null)
92+ .create().show();
93+ }
94+ File sdDir = new File(Environment.getExternalStorageDirectory().getPath());
95+ if (sdDir.exists() && sdDir.canWrite()) {
96+ File file = new File(sdDir.getAbsolutePath() + "/" + updateFilename);
97+ try {
98+ file.createNewFile();
99+ } catch (IOException e) {
100+ Log.e(TAG, "Couldn't create destination for " + updateFilename, e);
101+ }
102+ if (file.exists() && file.canWrite()) {
103+ FileInputStream fileIn;
104+ FileOutputStream fileOut;
105+ try {
106+ fileIn = mContext.openFileInput(updateFilename);
107+ fileOut = new FileOutputStream(file);
108+ byte[] reader = new byte[fileIn.available()];
109+ while (fileIn.read(reader) != -1);
110+ fileOut.write(reader);
111+ if (fileIn != null) {
112+ fileIn.close();
113+ }
114+ if (fileOut != null) {
115+ fileOut.close();
116+ }
117+ } catch (FileNotFoundException e) {
118+ Log.e(TAG, "Error:", e);
119+ } catch (IOException e) {
120+ Log.e(TAG, "Error:", e);
121+ }
122+ }
123+ }
124+ }
125+
126+ private class DownloadFileTask extends AsyncTask<String, Integer, String> {
127+
128+ @Override
129+ protected String doInBackground(String... params) {
130+ for (String s : params) {
131+ try {
132+ URL url = new URL(s);
133+ String file = s.substring(s.lastIndexOf("/") + 1);
134+
135+ URLConnection urlCon = url.openConnection();
136+ BufferedInputStream bis = new BufferedInputStream(urlCon.getInputStream());
137+
138+ ByteArrayBuffer baf = new ByteArrayBuffer(50);
139+ int current = 0;
140+ while ((current = bis.read()) != -1) {
141+ baf.append((byte) current);
142+ }
143+ if (file.equals("manifest.json")) {
144+ try {
145+ mManifest = new JSONObject(new String(baf.toByteArray()));
146+ } catch (JSONException e) {
147+ Log.e(TAG, "Bad JSON file", e);
148+ }
149+ } else {
150+ FileOutputStream fos = mContext.openFileOutput(file,
151+ Context.MODE_WORLD_READABLE);
152+ fos.write(baf.toByteArray());
153+ fos.close();
154+ }
155+ return file;
156+ } catch (MalformedURLException e) {
157+ Log.e(TAG, "Bad URL", e);
158+ } catch (IOException e) {
159+ Log.e(TAG, "Problem downloading file", e);
160+ }
161+ }
162+ return null;
163+ }
164+
165+ @Override
166+ protected void onPostExecute(String result) {
167+ if (result.equals("manifest.json")) {
168+ postManifest();
169+ } else if (result.equals("su")) {
170+ new AutoUpdateTask().execute();
171+ }
172+ }
173+ }
174+
175+ public class AutoUpdateTask extends AsyncTask<String, Integer, Boolean> {
176+
177+ @Override
178+ protected Boolean doInBackground(String... params) {
179+ String device = null;
180+ boolean foundSystem = false;
181+ try {
182+ Process process = Runtime.getRuntime().exec("mount");
183+ BufferedReader stdInput = new BufferedReader(new InputStreamReader(process.getInputStream()));
184+ String line;
185+ while ((line = stdInput.readLine()) != null) {
186+ String[] array = line.split(" ");
187+ device = array[0];
188+ if ((array[1].equals("on") && array[2].equals("/system")) ||
189+ array[1].equals("/system")) {
190+ foundSystem = true;
191+ break;
192+ }
193+ }
194+ } catch (IOException e) {
195+ Log.e(TAG, "Problem remounting /system", e);
196+ return false;
197+ }
198+
199+ if (foundSystem && device != null) {
200+ final String mountDev = device;
201+ Process process;
202+ try {
203+ process = Runtime.getRuntime().exec("su");
204+ DataOutputStream os = new DataOutputStream(process.getOutputStream());
205+ os.writeBytes("mount -o remount,rw " + mountDev + " /system\n");
206+ os.writeBytes("cat /data/data/com.noshufou.android.su/files/su > /system/bin/su\n");
207+ os.writeBytes("chmod 06755 /system/bin/su\n");
208+ os.writeBytes("cat /data/data/com.noshufou.android.su/files/su > /system/sbin/su\n");
209+ os.writeBytes("chmod 06755 /system/sbin/su\n");
210+ os.writeBytes("mount -o remount,ro " + mountDev + " /system\n");
211+ os.writeBytes("exit\n");
212+ try {
213+ process.waitFor();
214+ if (process.exitValue() != 255) {
215+ return true;
216+ } else {
217+ return false;
218+ }
219+ } catch (InterruptedException e) {
220+ return false;
221+ }
222+ } catch (IOException e) {
223+ return false;
224+ }
225+ }
226+ return false;
227+ }
228+
229+ @Override
230+ protected void onPostExecute(Boolean result) {
231+ if (result) {
232+ Toast.makeText(mContext, R.string.su_updated, Toast.LENGTH_SHORT).show();
233+ } else {
234+ copyUpdateZip(true);
235+ }
236+ }
237+ }
238+}