Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
C
com.ccwangluo.accelerator
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
sheteng
com.ccwangluo.accelerator
Commits
45daac82
Commit
45daac82
authored
Dec 21, 2012
by
Max Lv
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
clean up
parent
c6164acf
Changes
8
Hide whitespace changes
Inline
Side-by-side
Showing
8 changed files
with
313 additions
and
338 deletions
+313
-338
src/com/github/shadowsocks/AppManager.java
src/com/github/shadowsocks/AppManager.java
+67
-76
src/com/github/shadowsocks/Exec.java
src/com/github/shadowsocks/Exec.java
+1
-1
src/com/github/shadowsocks/ImageLoader.java
src/com/github/shadowsocks/ImageLoader.java
+85
-90
src/com/github/shadowsocks/Node.java
src/com/github/shadowsocks/Node.java
+1
-0
src/com/github/shadowsocks/ProxyedApp.java
src/com/github/shadowsocks/ProxyedApp.java
+30
-31
src/com/github/shadowsocks/Shadowsocks.java
src/com/github/shadowsocks/Shadowsocks.java
+2
-7
src/com/github/shadowsocks/ShadowsocksApplication.java
src/com/github/shadowsocks/ShadowsocksApplication.java
+0
-1
src/com/github/shadowsocks/Utils.java
src/com/github/shadowsocks/Utils.java
+127
-132
No files found.
src/com/github/shadowsocks/AppManager.java
View file @
45daac82
...
...
@@ -30,11 +30,67 @@ import java.util.*;
public
class
AppManager
extends
Activity
implements
OnCheckedChangeListener
,
OnClickListener
{
private
static
class
ListEntry
{
private
CheckBox
box
;
private
TextView
text
;
private
ImageView
icon
;
}
public
final
static
String
PREFS_KEY_PROXYED
=
"Proxyed"
;
private
static
final
int
MSG_LOAD_START
=
1
;
private
static
final
int
MSG_LOAD_FINISH
=
2
;
final
Handler
handler
=
new
Handler
()
{
@Override
public
void
handleMessage
(
Message
msg
)
{
switch
(
msg
.
what
)
{
case
MSG_LOAD_START:
pd
=
ProgressDialog
.
show
(
AppManager
.
this
,
""
,
getString
(
R
.
string
.
loading
),
true
,
true
);
break
;
case
MSG_LOAD_FINISH:
listApps
.
setAdapter
(
adapter
);
listApps
.
setOnScrollListener
(
new
OnScrollListener
()
{
boolean
visible
;
@Override
public
void
onScroll
(
AbsListView
view
,
int
firstVisibleItem
,
int
visibleItemCount
,
int
totalItemCount
)
{
if
(
visible
)
{
String
name
=
apps
[
firstVisibleItem
].
getName
();
if
(
name
!=
null
&&
name
.
length
()
>
1
)
overlay
.
setText
(
apps
[
firstVisibleItem
]
.
getName
().
substring
(
0
,
1
));
else
overlay
.
setText
(
"*"
);
overlay
.
setVisibility
(
View
.
VISIBLE
);
}
}
@Override
public
void
onScrollStateChanged
(
AbsListView
view
,
int
scrollState
)
{
visible
=
true
;
if
(
scrollState
==
OnScrollListener
.
SCROLL_STATE_IDLE
)
{
overlay
.
setVisibility
(
View
.
INVISIBLE
);
}
}
});
if
(
pd
!=
null
)
{
pd
.
dismiss
();
pd
=
null
;
}
break
;
}
super
.
handleMessage
(
msg
);
}
};
private
ProxyedApp
[]
apps
=
null
;
private
ListView
listApps
;
private
AppManager
mAppManager
;
private
TextView
overlay
;
private
ProgressDialog
pd
=
null
;
private
ListAdapter
adapter
;
private
ImageLoader
dm
;
private
boolean
appsLoaded
=
false
;
public
static
ProxyedApp
[]
getProxyedApps
(
Context
context
)
{
...
...
@@ -96,77 +152,6 @@ public class AppManager extends Activity implements OnCheckedChangeListener,
return
apps
;
}
private
ProxyedApp
[]
apps
=
null
;
private
ListView
listApps
;
private
AppManager
mAppManager
;
private
TextView
overlay
;
private
ProgressDialog
pd
=
null
;
private
ListAdapter
adapter
;
private
ImageLoader
dm
;
private
static
final
int
MSG_LOAD_START
=
1
;
private
static
final
int
MSG_LOAD_FINISH
=
2
;
public
final
static
String
PREFS_KEY_PROXYED
=
"Proxyed"
;
private
boolean
appsLoaded
=
false
;
final
Handler
handler
=
new
Handler
()
{
@Override
public
void
handleMessage
(
Message
msg
)
{
switch
(
msg
.
what
)
{
case
MSG_LOAD_START:
pd
=
ProgressDialog
.
show
(
AppManager
.
this
,
""
,
getString
(
R
.
string
.
loading
),
true
,
true
);
break
;
case
MSG_LOAD_FINISH:
listApps
.
setAdapter
(
adapter
);
listApps
.
setOnScrollListener
(
new
OnScrollListener
()
{
boolean
visible
;
@Override
public
void
onScroll
(
AbsListView
view
,
int
firstVisibleItem
,
int
visibleItemCount
,
int
totalItemCount
)
{
if
(
visible
)
{
String
name
=
apps
[
firstVisibleItem
].
getName
();
if
(
name
!=
null
&&
name
.
length
()
>
1
)
overlay
.
setText
(
apps
[
firstVisibleItem
]
.
getName
().
substring
(
0
,
1
));
else
overlay
.
setText
(
"*"
);
overlay
.
setVisibility
(
View
.
VISIBLE
);
}
}
@Override
public
void
onScrollStateChanged
(
AbsListView
view
,
int
scrollState
)
{
visible
=
true
;
if
(
scrollState
==
OnScrollListener
.
SCROLL_STATE_IDLE
)
{
overlay
.
setVisibility
(
View
.
INVISIBLE
);
}
}
});
if
(
pd
!=
null
)
{
pd
.
dismiss
();
pd
=
null
;
}
break
;
}
super
.
handleMessage
(
msg
);
}
};
public
void
getApps
(
Context
context
)
{
SharedPreferences
prefs
=
PreferenceManager
...
...
@@ -413,4 +398,10 @@ public class AppManager extends Activity implements OnCheckedChangeListener,
}
private
static
class
ListEntry
{
private
CheckBox
box
;
private
TextView
text
;
private
ImageView
icon
;
}
}
src/com/github/shadowsocks/Exec.java
View file @
45daac82
...
...
@@ -51,7 +51,7 @@ public class Exec {
* @param scripts The scripts to execute.
* @param processId A one-element array to which the process ID of the started
* process will be written.
* @return
File descriptor
* @return File descriptor
*/
public
static
native
FileDescriptor
createSubprocess
(
int
rdt
,
String
cmd
,
String
[]
args
,
String
[]
envVars
,
...
...
src/com/github/shadowsocks/ImageLoader.java
View file @
45daac82
...
...
@@ -16,101 +16,15 @@ import java.util.Stack;
public
class
ImageLoader
{
// Used to display bitmap in the UI thread
class
BitmapDisplayer
implements
Runnable
{
Bitmap
bitmap
;
ImageView
imageView
;
public
BitmapDisplayer
(
Bitmap
b
,
ImageView
i
)
{
bitmap
=
b
;
imageView
=
i
;
}
@Override
public
void
run
()
{
if
(
bitmap
!=
null
)
imageView
.
setImageBitmap
(
bitmap
);
else
imageView
.
setImageResource
(
stub_id
);
}
}
class
PhotosLoader
extends
Thread
{
@Override
public
void
run
()
{
try
{
while
(
true
)
{
// thread waits until there are any images to load in the
// queue
if
(
photosQueue
.
photosToLoad
.
size
()
==
0
)
synchronized
(
photosQueue
.
photosToLoad
)
{
photosQueue
.
photosToLoad
.
wait
();
}
if
(
photosQueue
.
photosToLoad
.
size
()
!=
0
)
{
PhotoToLoad
photoToLoad
;
synchronized
(
photosQueue
.
photosToLoad
)
{
photoToLoad
=
photosQueue
.
photosToLoad
.
pop
();
}
Bitmap
bmp
=
getBitmap
(
photoToLoad
.
uid
);
cache
.
put
(
photoToLoad
.
uid
,
bmp
);
Object
tag
=
photoToLoad
.
imageView
.
getTag
();
if
(
tag
!=
null
&&
((
Integer
)
tag
)
==
photoToLoad
.
uid
)
{
BitmapDisplayer
bd
=
new
BitmapDisplayer
(
bmp
,
photoToLoad
.
imageView
);
Activity
a
=
(
Activity
)
photoToLoad
.
imageView
.
getContext
();
a
.
runOnUiThread
(
bd
);
}
}
if
(
Thread
.
interrupted
())
break
;
}
}
catch
(
InterruptedException
e
)
{
// allow thread to exit
}
}
}
// stores list of photos to download
class
PhotosQueue
{
private
final
Stack
<
PhotoToLoad
>
photosToLoad
=
new
Stack
<
PhotoToLoad
>();
// removes all instances of this ImageView
public
void
Clean
(
ImageView
image
)
{
synchronized
(
photosToLoad
)
{
for
(
int
j
=
0
;
j
<
photosToLoad
.
size
();
)
{
if
(
photosToLoad
.
get
(
j
).
imageView
==
image
)
photosToLoad
.
remove
(
j
);
else
++
j
;
}
}
}
}
// Task for the queue
private
class
PhotoToLoad
{
public
int
uid
;
public
ImageView
imageView
;
public
PhotoToLoad
(
int
u
,
ImageView
i
)
{
uid
=
u
;
imageView
=
i
;
}
}
final
int
stub_id
=
R
.
drawable
.
sym_def_app_icon
;
PhotosQueue
photosQueue
=
new
PhotosQueue
();
PhotosLoader
photoLoaderThread
=
new
PhotosLoader
();
// the simplest in-memory cache implementation. This should be replaced with
// something like SoftReference or BitmapOptions.inPurgeable(since 1.6)
private
HashMap
<
Integer
,
Bitmap
>
cache
=
new
HashMap
<
Integer
,
Bitmap
>();
private
File
cacheDir
;
private
Context
context
;
final
int
stub_id
=
R
.
drawable
.
sym_def_app_icon
;
PhotosQueue
photosQueue
=
new
PhotosQueue
();
PhotosLoader
photoLoaderThread
=
new
PhotosLoader
();
public
ImageLoader
(
Context
c
)
{
// Make the background thead low priority. This way it will not affect
// the UI performance
...
...
@@ -158,7 +72,7 @@ public class ImageLoader {
BitmapFactory
.
Options
o2
=
new
BitmapFactory
.
Options
();
o2
.
inSampleSize
=
scale
;
return
BitmapFactory
.
decodeStream
(
new
FileInputStream
(
f
),
null
,
o2
);
}
catch
(
FileNotFoundException
e
)
{
}
catch
(
FileNotFoundException
ignored
)
{
}
return
null
;
}
...
...
@@ -212,4 +126,85 @@ public class ImageLoader {
photoLoaderThread
.
interrupt
();
}
// Used to display bitmap in the UI thread
class
BitmapDisplayer
implements
Runnable
{
Bitmap
bitmap
;
ImageView
imageView
;
public
BitmapDisplayer
(
Bitmap
b
,
ImageView
i
)
{
bitmap
=
b
;
imageView
=
i
;
}
@Override
public
void
run
()
{
if
(
bitmap
!=
null
)
imageView
.
setImageBitmap
(
bitmap
);
else
imageView
.
setImageResource
(
stub_id
);
}
}
class
PhotosLoader
extends
Thread
{
@Override
public
void
run
()
{
try
{
while
(
true
)
{
// thread waits until there are any images to load in the
// queue
if
(
photosQueue
.
photosToLoad
.
size
()
==
0
)
synchronized
(
photosQueue
.
photosToLoad
)
{
photosQueue
.
photosToLoad
.
wait
();
}
if
(
photosQueue
.
photosToLoad
.
size
()
!=
0
)
{
PhotoToLoad
photoToLoad
;
synchronized
(
photosQueue
.
photosToLoad
)
{
photoToLoad
=
photosQueue
.
photosToLoad
.
pop
();
}
Bitmap
bmp
=
getBitmap
(
photoToLoad
.
uid
);
cache
.
put
(
photoToLoad
.
uid
,
bmp
);
Object
tag
=
photoToLoad
.
imageView
.
getTag
();
if
(
tag
!=
null
&&
((
Integer
)
tag
)
==
photoToLoad
.
uid
)
{
BitmapDisplayer
bd
=
new
BitmapDisplayer
(
bmp
,
photoToLoad
.
imageView
);
Activity
a
=
(
Activity
)
photoToLoad
.
imageView
.
getContext
();
a
.
runOnUiThread
(
bd
);
}
}
if
(
Thread
.
interrupted
())
break
;
}
}
catch
(
InterruptedException
e
)
{
// allow thread to exit
}
}
}
// stores list of photos to download
class
PhotosQueue
{
private
final
Stack
<
PhotoToLoad
>
photosToLoad
=
new
Stack
<
PhotoToLoad
>();
// removes all instances of this ImageView
public
void
Clean
(
ImageView
image
)
{
synchronized
(
photosToLoad
)
{
for
(
int
j
=
0
;
j
<
photosToLoad
.
size
();
)
{
if
(
photosToLoad
.
get
(
j
).
imageView
==
image
)
photosToLoad
.
remove
(
j
);
else
++
j
;
}
}
}
}
// Task for the queue
private
class
PhotoToLoad
{
public
int
uid
;
public
ImageView
imageView
;
public
PhotoToLoad
(
int
u
,
ImageView
i
)
{
uid
=
u
;
imageView
=
i
;
}
}
}
src/com/github/shadowsocks/Node.java
100644 → 100755
View file @
45daac82
...
...
@@ -4,5 +4,6 @@ public class Node {
static
{
System
.
loadLibrary
(
"node"
);
}
public
static
native
void
exec
(
String
cmd
);
}
src/com/github/shadowsocks/ProxyedApp.java
View file @
45daac82
...
...
@@ -7,7 +7,6 @@ public class ProxyedApp {
private
String
username
;
private
String
procname
;
private
String
name
;
private
boolean
proxyed
=
false
;
/**
...
...
@@ -17,6 +16,13 @@ public class ProxyedApp {
return
name
;
}
/**
* @param name the name to set
*/
public
void
setName
(
String
name
)
{
this
.
name
=
name
;
}
/**
* @return the procname
*/
...
...
@@ -24,6 +30,13 @@ public class ProxyedApp {
return
procname
;
}
/**
* @param procname the procname to set
*/
public
void
setProcname
(
String
procname
)
{
this
.
procname
=
procname
;
}
/**
* @return the uid
*/
...
...
@@ -31,6 +44,13 @@ public class ProxyedApp {
return
uid
;
}
/**
* @param uid the uid to set
*/
public
void
setUid
(
int
uid
)
{
this
.
uid
=
uid
;
}
/**
* @return the username
*/
...
...
@@ -39,17 +59,17 @@ public class ProxyedApp {
}
/**
* @
return the enabled
* @
param username the username to set
*/
public
boolean
isEnabled
(
)
{
return
enabled
;
public
void
setUsername
(
String
username
)
{
this
.
username
=
username
;
}
/**
* @return the
proxy
ed
* @return the
enabl
ed
*/
public
boolean
is
Proxy
ed
()
{
return
proxy
ed
;
public
boolean
is
Enabl
ed
()
{
return
enabl
ed
;
}
/**
...
...
@@ -60,17 +80,10 @@ public class ProxyedApp {
}
/**
* @param name the name to set
*/
public
void
setName
(
String
name
)
{
this
.
name
=
name
;
}
/**
* @param procname the procname to set
* @return the proxyed
*/
public
void
setProcname
(
String
procname
)
{
this
.
procname
=
procname
;
public
boolean
isProxyed
(
)
{
return
proxyed
;
}
/**
...
...
@@ -79,18 +92,4 @@ public class ProxyedApp {
public
void
setProxyed
(
boolean
proxyed
)
{
this
.
proxyed
=
proxyed
;
}
/**
* @param uid the uid to set
*/
public
void
setUid
(
int
uid
)
{
this
.
uid
=
uid
;
}
/**
* @param username the username to set
*/
public
void
setUsername
(
String
username
)
{
this
.
username
=
username
;
}
}
\ No newline at end of file
src/com/github/shadowsocks/Shadowsocks.java
View file @
45daac82
...
...
@@ -66,13 +66,11 @@ import java.io.OutputStream;
public
class
Shadowsocks
extends
PreferenceActivity
implements
OnSharedPreferenceChangeListener
{
private
static
final
String
TAG
=
"Shadowsocks"
;
public
static
final
String
PREFS_NAME
=
"Shadowsocks"
;
private
static
final
String
TAG
=
"Shadowsocks"
;
private
static
final
int
MSG_CRASH_RECOVER
=
1
;
private
static
final
int
MSG_INITIAL_FINISH
=
2
;
private
static
ProgressDialog
mProgressDialog
=
null
;
final
Handler
handler
=
new
Handler
()
{
@Override
public
void
handleMessage
(
Message
msg
)
{
...
...
@@ -96,9 +94,6 @@ public class Shadowsocks extends PreferenceActivity implements
super
.
handleMessage
(
msg
);
}
};
private
static
ProgressDialog
mProgressDialog
=
null
;
private
EditTextPreference
proxyText
;
private
EditTextPreference
portText
;
private
EditTextPreference
remotePortText
;
...
...
src/com/github/shadowsocks/ShadowsocksApplication.java
View file @
45daac82
package
com.github.shadowsocks
;
import
android.app.Application
;
import
android.content.Context
;
import
com.google.analytics.tracking.android.EasyTracker
;
public
class
ShadowsocksApplication
extends
Application
{
...
...
src/com/github/shadowsocks/Utils.java
View file @
45daac82
...
...
@@ -16,151 +16,19 @@ import java.util.ArrayList;
public
class
Utils
{
/**
* Internal thread used to execute scripts (as root or not).
*/
private
static
final
class
ScriptRunner
extends
Thread
{
private
final
String
scripts
;
private
final
StringBuilder
result
;
private
final
boolean
asroot
;
public
int
exitcode
=
-
1
;
/**
* Creates a new script runner.
*
* @param script script to run
* @param result result output
* @param asroot if true, executes the script as root
*/
public
ScriptRunner
(
String
script
,
StringBuilder
result
,
boolean
asroot
)
{
this
.
scripts
=
script
;
this
.
result
=
result
;
this
.
asroot
=
asroot
;
}
private
FileDescriptor
createSubprocess
(
int
[]
processId
,
String
cmd
)
{
ArrayList
<
String
>
argList
=
parse
(
cmd
);
String
arg0
=
argList
.
get
(
0
);
String
[]
args
=
argList
.
toArray
(
new
String
[
1
]);
return
Exec
.
createSubprocess
(
result
!=
null
?
1
:
0
,
arg0
,
args
,
null
,
scripts
+
"\nexit\n"
,
processId
);
}
private
ArrayList
<
String
>
parse
(
String
cmd
)
{
final
int
PLAIN
=
0
;
final
int
WHITESPACE
=
1
;
final
int
INQUOTE
=
2
;
int
state
=
WHITESPACE
;
ArrayList
<
String
>
result
=
new
ArrayList
<
String
>();
int
cmdLen
=
cmd
.
length
();
StringBuilder
builder
=
new
StringBuilder
();
for
(
int
i
=
0
;
i
<
cmdLen
;
i
++)
{
char
c
=
cmd
.
charAt
(
i
);
if
(
state
==
PLAIN
)
{
if
(
Character
.
isWhitespace
(
c
))
{
result
.
add
(
builder
.
toString
());
builder
.
delete
(
0
,
builder
.
length
());
state
=
WHITESPACE
;
}
else
if
(
c
==
'"'
)
{
state
=
INQUOTE
;
}
else
{
builder
.
append
(
c
);
}
}
else
if
(
state
==
WHITESPACE
)
{
if
(
Character
.
isWhitespace
(
c
))
{
// do nothing
}
else
if
(
c
==
'"'
)
{
state
=
INQUOTE
;
}
else
{
state
=
PLAIN
;
builder
.
append
(
c
);
}
}
else
if
(
state
==
INQUOTE
)
{
if
(
c
==
'\\'
)
{
if
(
i
+
1
<
cmdLen
)
{
i
+=
1
;
builder
.
append
(
cmd
.
charAt
(
i
));
}
}
else
if
(
c
==
'"'
)
{
state
=
PLAIN
;
}
else
{
builder
.
append
(
c
);
}
}
}
if
(
builder
.
length
()
>
0
)
{
result
.
add
(
builder
.
toString
());
}
return
result
;
}
@Override
public
void
run
()
{
FileDescriptor
pipe
=
null
;
int
pid
[]
=
new
int
[
1
];
pid
[
0
]
=
-
1
;
try
{
if
(
this
.
asroot
)
{
// Create the "su" request to run the script
pipe
=
createSubprocess
(
pid
,
root_shell
);
}
else
{
// Create the "sh" request to run the script
pipe
=
createSubprocess
(
pid
,
getShell
());
}
if
(
pid
[
0
]
!=
-
1
)
{
exitcode
=
Exec
.
waitFor
(
pid
[
0
]);
}
if
(
result
==
null
||
pipe
==
null
)
return
;
final
InputStream
stdout
=
new
FileInputStream
(
pipe
);
final
byte
buf
[]
=
new
byte
[
8192
];
int
read
=
0
;
// Read stdout
while
(
stdout
.
available
()
>
0
)
{
read
=
stdout
.
read
(
buf
);
result
.
append
(
new
String
(
buf
,
0
,
read
));
}
}
catch
(
Exception
ex
)
{
Log
.
e
(
TAG
,
"Cannot execute command"
,
ex
);
if
(
result
!=
null
)
result
.
append
(
"\n"
).
append
(
ex
);
}
finally
{
if
(
pipe
!=
null
)
{
Exec
.
close
(
pipe
);
}
if
(
pid
[
0
]
!=
-
1
)
{
Exec
.
hangupProcessGroup
(
pid
[
0
]);
}
}
}
}
public
final
static
String
TAG
=
"Shadowsocks"
;
public
final
static
String
DEFAULT_SHELL
=
"/system/bin/sh"
;
public
final
static
String
DEFAULT_ROOT
=
"/system/bin/su"
;
public
final
static
String
ALTERNATIVE_ROOT
=
"/system/xbin/su"
;
public
final
static
String
DEFAULT_IPTABLES
=
"/data/data/com.github.shadowsocks/iptables"
;
public
final
static
String
ALTERNATIVE_IPTABLES
=
"/system/bin/iptables"
;
public
final
static
int
TIME_OUT
=
-
99
;
private
static
boolean
initialized
=
false
;
private
static
int
hasRedirectSupport
=
-
1
;
private
static
int
isRoot
=
-
1
;
private
static
String
shell
=
null
;
private
static
String
root_shell
=
null
;
private
static
String
iptables
=
null
;
private
static
String
data_path
=
null
;
private
static
void
checkIptables
()
{
...
...
@@ -393,4 +261,131 @@ public class Utils {
}
return
runner
.
exitcode
;
}
/**
* Internal thread used to execute scripts (as root or not).
*/
private
static
final
class
ScriptRunner
extends
Thread
{
private
final
String
scripts
;
private
final
StringBuilder
result
;
private
final
boolean
asroot
;
public
int
exitcode
=
-
1
;
/**
* Creates a new script runner.
*
* @param script script to run
* @param result result output
* @param asroot if true, executes the script as root
*/
public
ScriptRunner
(
String
script
,
StringBuilder
result
,
boolean
asroot
)
{
this
.
scripts
=
script
;
this
.
result
=
result
;
this
.
asroot
=
asroot
;
}
private
FileDescriptor
createSubprocess
(
int
[]
processId
,
String
cmd
)
{
ArrayList
<
String
>
argList
=
parse
(
cmd
);
String
arg0
=
argList
.
get
(
0
);
String
[]
args
=
argList
.
toArray
(
new
String
[
1
]);
return
Exec
.
createSubprocess
(
result
!=
null
?
1
:
0
,
arg0
,
args
,
null
,
scripts
+
"\nexit\n"
,
processId
);
}
private
ArrayList
<
String
>
parse
(
String
cmd
)
{
final
int
PLAIN
=
0
;
final
int
WHITESPACE
=
1
;
final
int
INQUOTE
=
2
;
int
state
=
WHITESPACE
;
ArrayList
<
String
>
result
=
new
ArrayList
<
String
>();
int
cmdLen
=
cmd
.
length
();
StringBuilder
builder
=
new
StringBuilder
();
for
(
int
i
=
0
;
i
<
cmdLen
;
i
++)
{
char
c
=
cmd
.
charAt
(
i
);
if
(
state
==
PLAIN
)
{
if
(
Character
.
isWhitespace
(
c
))
{
result
.
add
(
builder
.
toString
());
builder
.
delete
(
0
,
builder
.
length
());
state
=
WHITESPACE
;
}
else
if
(
c
==
'"'
)
{
state
=
INQUOTE
;
}
else
{
builder
.
append
(
c
);
}
}
else
if
(
state
==
WHITESPACE
)
{
if
(
Character
.
isWhitespace
(
c
))
{
// do nothing
}
else
if
(
c
==
'"'
)
{
state
=
INQUOTE
;
}
else
{
state
=
PLAIN
;
builder
.
append
(
c
);
}
}
else
if
(
state
==
INQUOTE
)
{
if
(
c
==
'\\'
)
{
if
(
i
+
1
<
cmdLen
)
{
i
+=
1
;
builder
.
append
(
cmd
.
charAt
(
i
));
}
}
else
if
(
c
==
'"'
)
{
state
=
PLAIN
;
}
else
{
builder
.
append
(
c
);
}
}
}
if
(
builder
.
length
()
>
0
)
{
result
.
add
(
builder
.
toString
());
}
return
result
;
}
@Override
public
void
run
()
{
FileDescriptor
pipe
=
null
;
int
pid
[]
=
new
int
[
1
];
pid
[
0
]
=
-
1
;
try
{
if
(
this
.
asroot
)
{
// Create the "su" request to run the script
pipe
=
createSubprocess
(
pid
,
root_shell
);
}
else
{
// Create the "sh" request to run the script
pipe
=
createSubprocess
(
pid
,
getShell
());
}
if
(
pid
[
0
]
!=
-
1
)
{
exitcode
=
Exec
.
waitFor
(
pid
[
0
]);
}
if
(
result
==
null
||
pipe
==
null
)
return
;
final
InputStream
stdout
=
new
FileInputStream
(
pipe
);
final
byte
buf
[]
=
new
byte
[
8192
];
int
read
=
0
;
// Read stdout
while
(
stdout
.
available
()
>
0
)
{
read
=
stdout
.
read
(
buf
);
result
.
append
(
new
String
(
buf
,
0
,
read
));
}
}
catch
(
Exception
ex
)
{
Log
.
e
(
TAG
,
"Cannot execute command"
,
ex
);
if
(
result
!=
null
)
result
.
append
(
"\n"
).
append
(
ex
);
}
finally
{
if
(
pipe
!=
null
)
{
Exec
.
close
(
pipe
);
}
if
(
pid
[
0
]
!=
-
1
)
{
Exec
.
hangupProcessGroup
(
pid
[
0
]);
}
}
}
}
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment