Commit 0191d1d0 authored by Mygod's avatar Mygod

Download acl files from GitHub

parent 6a56704f
......@@ -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"
......
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
}
}
}
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
}
}
}
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))
}
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment