Download acl files from GitHub
This commit is contained in:
@@ -36,12 +36,12 @@ libraryDependencies ++= Seq(
|
||||
"com.android.support" % "design" % "24.2.1",
|
||||
"com.android.support" % "gridlayout-v7" % "24.2.1",
|
||||
"com.android.support" % "preference-v14" % "24.2.1",
|
||||
"com.evernote" % "android-job" % "1.1.0",
|
||||
"com.github.clans" % "fab" % "1.6.4",
|
||||
"com.github.jorgecastilloprz" % "fabprogresscircle" % "1.01",
|
||||
"com.github.kevinsawicki" % "http-request" % "6.0",
|
||||
"com.google.android.gms" % "play-services-ads" % "9.6.1",
|
||||
"com.google.android.gms" % "play-services-analytics" % "9.6.1",
|
||||
"com.google.firebase" % "firebase-storage" % "9.6.1",
|
||||
"com.j256.ormlite" % "ormlite-android" % "5.0",
|
||||
"com.twofortyfouram" % "android-plugin-api-for-locale" % "1.0.2",
|
||||
"dnsjava" % "dnsjava" % "2.1.7",
|
||||
|
||||
@@ -39,7 +39,7 @@
|
||||
|
||||
package com.github.shadowsocks
|
||||
|
||||
import java.io.{File, IOException}
|
||||
import java.io.IOException
|
||||
import java.util.{Timer, TimerTask}
|
||||
|
||||
import android.app.Service
|
||||
@@ -54,8 +54,6 @@ import com.github.shadowsocks.ShadowsocksApplication.app
|
||||
import com.github.shadowsocks.aidl.{IShadowsocksService, IShadowsocksServiceCallback}
|
||||
import com.github.shadowsocks.database.Profile
|
||||
import com.github.shadowsocks.utils._
|
||||
import com.google.firebase.FirebaseApp
|
||||
import com.google.firebase.storage.FirebaseStorage
|
||||
|
||||
trait BaseService extends Service {
|
||||
|
||||
@@ -278,7 +276,6 @@ trait BaseService extends Service {
|
||||
|
||||
override def onCreate() {
|
||||
super.onCreate()
|
||||
FirebaseApp.initializeApp(this)
|
||||
app.refreshContainerHolder
|
||||
app.updateAssets()
|
||||
}
|
||||
@@ -315,33 +312,4 @@ trait BaseService extends Service {
|
||||
case ex: Exception => "exclude = " + default + ";"
|
||||
}
|
||||
}
|
||||
|
||||
def fetchAcl(route: String) {
|
||||
val localAcl = route match {
|
||||
case Route.BYPASS_LAN => "bypass_lan.acl"
|
||||
case Route.BYPASS_CHN => "bypass_chn.acl"
|
||||
case Route.BYPASS_LAN_CHN => "bypass_lan_chn.acl"
|
||||
case Route.GFWLIST => "gfwlist.acl"
|
||||
case Route.CHINALIST => "chinalist.acl"
|
||||
}
|
||||
val cloudAclFile = new File(getApplicationInfo.dataDir + "/" + localAcl)
|
||||
if (!cloudAclFile.exists) cloudAclFile.createNewFile
|
||||
val tempFile = File.createTempFile(localAcl, "acl")
|
||||
val storage = FirebaseStorage.getInstance
|
||||
val storageRef = storage.getReferenceFromUrl("gs://admob-app-id-3330146721.appspot.com/acl/")
|
||||
val aclRef = storageRef.child(localAcl)
|
||||
|
||||
val task = aclRef.getFile(tempFile)
|
||||
task.addOnSuccessListener(_ => {
|
||||
if (!tempFile.renameTo(cloudAclFile)) {
|
||||
Log.d("shadowsocks", "Failed to rename acl file")
|
||||
if (!tempFile.delete()) tempFile.deleteOnExit()
|
||||
}
|
||||
return
|
||||
})
|
||||
task.addOnFailureListener(_ => {
|
||||
Log.e("shadowsocks", "Unable to download " + localAcl)
|
||||
if (!tempFile.delete()) tempFile.deleteOnExit()
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -39,7 +39,7 @@
|
||||
|
||||
package com.github.shadowsocks
|
||||
|
||||
import java.io.{FileOutputStream, IOException, InputStream, OutputStream}
|
||||
import java.io.{FileOutputStream, IOException}
|
||||
import java.util
|
||||
import java.util.Locale
|
||||
import java.util.concurrent.TimeUnit
|
||||
@@ -51,9 +51,11 @@ import android.os.{Build, LocaleList}
|
||||
import android.preference.PreferenceManager
|
||||
import android.support.v7.app.AppCompatDelegate
|
||||
import android.util.Log
|
||||
import com.evernote.android.job.JobManager
|
||||
import com.github.shadowsocks.database.{DBHelper, ProfileManager}
|
||||
import com.github.shadowsocks.job.DonaldTrump
|
||||
import com.github.shadowsocks.utils.CloseUtils._
|
||||
import com.github.shadowsocks.utils.{Executable, Key, TcpFastOpen, Utils}
|
||||
import com.github.shadowsocks.utils._
|
||||
import com.google.android.gms.analytics.{GoogleAnalytics, HitBuilders, StandardExceptionParser}
|
||||
import com.google.android.gms.common.api.ResultCallback
|
||||
import com.google.android.gms.tagmanager.{ContainerHolder, TagManager}
|
||||
@@ -181,6 +183,7 @@ class ShadowsocksApplication extends Application {
|
||||
}
|
||||
}
|
||||
pending.setResultCallback(callback, 2, TimeUnit.SECONDS)
|
||||
JobManager.create(this).addJobCreator(DonaldTrump)
|
||||
|
||||
TcpFastOpen.enabled(settings.getBoolean(Key.tfo, TcpFastOpen.sendEnabled))
|
||||
}
|
||||
@@ -190,14 +193,6 @@ class ShadowsocksApplication extends Application {
|
||||
if (holder != null) holder.refresh()
|
||||
}
|
||||
|
||||
private def copyStream(in: InputStream, out: OutputStream) {
|
||||
val buffer = new Array[Byte](1024)
|
||||
while (true) {
|
||||
val count = in.read(buffer)
|
||||
if (count < 0) return else out.write(buffer, 0, count)
|
||||
}
|
||||
}
|
||||
|
||||
private def copyAssets(path: String) {
|
||||
val assetManager = getAssets
|
||||
var files: Array[String] = null
|
||||
@@ -209,7 +204,7 @@ class ShadowsocksApplication extends Application {
|
||||
if (files != null) for (file <- files)
|
||||
autoClose(assetManager.open(if (path.nonEmpty) path + '/' + file else file))(in =>
|
||||
autoClose(new FileOutputStream(getApplicationInfo.dataDir + '/' + file))(out =>
|
||||
copyStream(in, out)))
|
||||
IOUtils.copy(in, out)))
|
||||
}
|
||||
|
||||
def copyAssets() {
|
||||
|
||||
@@ -48,6 +48,7 @@ import android.os._
|
||||
import android.util.Log
|
||||
import com.github.shadowsocks.ShadowsocksApplication.app
|
||||
import com.github.shadowsocks.database.Profile
|
||||
import com.github.shadowsocks.job.AclSyncJob
|
||||
import com.github.shadowsocks.utils._
|
||||
import eu.chainfire.libsuperuser.Shell
|
||||
|
||||
@@ -96,14 +97,7 @@ class ShadowsocksNatService extends BaseService {
|
||||
|
||||
if (profile.route != Route.ALL) {
|
||||
cmd += "--acl"
|
||||
|
||||
profile.route match {
|
||||
case Route.BYPASS_LAN => cmd += (getApplicationInfo.dataDir + "/bypass_lan.acl")
|
||||
case Route.BYPASS_CHN => cmd += (getApplicationInfo.dataDir + "/bypass_chn.acl")
|
||||
case Route.BYPASS_LAN_CHN => cmd += (getApplicationInfo.dataDir + "/bypass_lan_chn.acl")
|
||||
case Route.GFWLIST => cmd += (getApplicationInfo.dataDir + "/gfwlist.acl")
|
||||
case Route.CHINALIST => cmd += (getApplicationInfo.dataDir + "/chinalist.acl")
|
||||
}
|
||||
cmd += getApplicationInfo.dataDir + '/' + profile.route + ".acl"
|
||||
}
|
||||
|
||||
if (BuildConfig.DEBUG) Log.d(TAG, cmd.mkString(" "))
|
||||
@@ -338,8 +332,7 @@ class ShadowsocksNatService extends BaseService {
|
||||
|
||||
handleConnection()
|
||||
|
||||
// lazily get ACL from cloud
|
||||
fetchAcl(profile.route)
|
||||
AclSyncJob.schedule(profile.route)
|
||||
|
||||
changeState(State.CONNECTED)
|
||||
notification = new ShadowsocksNotification(this, profile.name, true)
|
||||
|
||||
@@ -50,6 +50,7 @@ import android.os._
|
||||
import android.util.Log
|
||||
import com.github.shadowsocks.ShadowsocksApplication.app
|
||||
import com.github.shadowsocks.database.Profile
|
||||
import com.github.shadowsocks.job.AclSyncJob
|
||||
import com.github.shadowsocks.utils._
|
||||
|
||||
import scala.collection.mutable.ArrayBuffer
|
||||
@@ -163,8 +164,7 @@ class ShadowsocksVpnService extends VpnService with BaseService {
|
||||
handleConnection()
|
||||
changeState(State.CONNECTED)
|
||||
|
||||
// lazily get ACL from cloud
|
||||
fetchAcl(profile.route)
|
||||
AclSyncJob.schedule(profile.route)
|
||||
|
||||
notification = new ShadowsocksNotification(this, profile.name)
|
||||
}
|
||||
@@ -261,14 +261,7 @@ class ShadowsocksVpnService extends VpnService with BaseService {
|
||||
|
||||
if (profile.route != Route.ALL) {
|
||||
cmd += "--acl"
|
||||
|
||||
profile.route match {
|
||||
case Route.BYPASS_LAN => cmd += (getApplicationInfo.dataDir + "/bypass_lan.acl")
|
||||
case Route.BYPASS_CHN => cmd += (getApplicationInfo.dataDir + "/bypass_chn.acl")
|
||||
case Route.BYPASS_LAN_CHN => cmd += (getApplicationInfo.dataDir + "/bypass_lan_chn.acl")
|
||||
case Route.GFWLIST => cmd += (getApplicationInfo.dataDir + "/gfwlist.acl")
|
||||
case Route.CHINALIST => cmd += (getApplicationInfo.dataDir + "/chinalist.acl")
|
||||
}
|
||||
cmd += getApplicationInfo.dataDir + '/' + profile.route + ".acl"
|
||||
}
|
||||
|
||||
if (TcpFastOpen.sendEnabled) cmd += "--fast-open"
|
||||
|
||||
@@ -0,0 +1,45 @@
|
||||
package com.github.shadowsocks.job
|
||||
|
||||
import java.io.IOException
|
||||
import java.net.URL
|
||||
|
||||
import com.evernote.android.job.Job.{Params, Result}
|
||||
import com.evernote.android.job.{Job, JobRequest}
|
||||
import com.github.shadowsocks.ShadowsocksApplication.app
|
||||
import com.github.shadowsocks.utils.CloseUtils._
|
||||
import com.github.shadowsocks.utils.IOUtils
|
||||
|
||||
/**
|
||||
* @author Mygod
|
||||
*/
|
||||
object AclSyncJob {
|
||||
final val TAG = "AclSyncJob"
|
||||
|
||||
def schedule(route: String) = new JobRequest.Builder(AclSyncJob.TAG + ':' + route)
|
||||
.setExecutionWindow(1, 10000)
|
||||
.setRequirementsEnforced(true)
|
||||
.setRequiredNetworkType(JobRequest.NetworkType.UNMETERED)
|
||||
.setRequiresCharging(true)
|
||||
.setUpdateCurrent(true)
|
||||
.build().schedule()
|
||||
}
|
||||
|
||||
class AclSyncJob(route: String) extends Job {
|
||||
override def onRunJob(params: Params): Result = {
|
||||
val filename = route + ".acl"
|
||||
try {
|
||||
//noinspection JavaAccessorMethodCalledAsEmptyParen
|
||||
IOUtils.writeString(app.getApplicationInfo.dataDir + '/' + filename, autoClose(
|
||||
new URL("https://raw.githubusercontent.com/shadowsocks/shadowsocks-android/master/src/main/assets/acl/" +
|
||||
filename).openConnection().getInputStream())(IOUtils.readString))
|
||||
Result.SUCCESS
|
||||
} catch {
|
||||
case e: IOException =>
|
||||
e.printStackTrace()
|
||||
Result.RESCHEDULE
|
||||
case e: Exception => // unknown failures, probably shouldn't retry
|
||||
e.printStackTrace()
|
||||
Result.FAILURE
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
package com.github.shadowsocks.job
|
||||
|
||||
import android.util.Log
|
||||
import com.evernote.android.job.JobCreator
|
||||
|
||||
/**
|
||||
* “I create jobs all day long.
|
||||
* - Donald Trump, 2015
|
||||
*
|
||||
* Source: http://www.cnn.com/2015/09/24/politics/donald-trump-marco-rubio-foreign-policy/
|
||||
*
|
||||
* @author !Mygod
|
||||
*/
|
||||
object DonaldTrump extends JobCreator {
|
||||
def create(tag: String) = {
|
||||
val parts = tag.split(":")
|
||||
parts(0) match {
|
||||
case AclSyncJob.TAG => new AclSyncJob(parts(1))
|
||||
case _ =>
|
||||
Log.w("BillClinton", "Unknown job tag: " + tag)
|
||||
null
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
package com.github.shadowsocks.utils
|
||||
|
||||
import com.github.shadowsocks.utils.CloseUtils._
|
||||
import java.io.{FileWriter, InputStream, OutputStream}
|
||||
|
||||
/**
|
||||
* @author Mygod
|
||||
*/
|
||||
object IOUtils {
|
||||
private final val BUFFER_SIZE = 32 * 1024
|
||||
|
||||
def copy(in: InputStream, out: OutputStream) {
|
||||
val buffer = new Array[Byte](BUFFER_SIZE)
|
||||
while (true) {
|
||||
val count = in.read(buffer)
|
||||
if (count >= 0) out.write(buffer, 0, count) else return
|
||||
}
|
||||
}
|
||||
|
||||
def readString(in: InputStream): String = {
|
||||
val builder = new StringBuilder()
|
||||
val buffer = new Array[Byte](BUFFER_SIZE)
|
||||
while (true) {
|
||||
val count = in.read(buffer)
|
||||
if (count >= 0) builder.append(new String(buffer, 0, count)) else return builder.toString()
|
||||
}
|
||||
null
|
||||
}
|
||||
|
||||
def writeString(file: String, content: String) = autoClose(new FileWriter(file))(writer => writer.write(content))
|
||||
}
|
||||
Reference in New Issue
Block a user