Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
253286c482 | ||
|
|
f25406b86c | ||
|
|
2c8718163a | ||
|
|
450bde5305 | ||
|
|
d51bf46413 | ||
|
|
a69183cc0f | ||
|
|
62a0bb59c7 | ||
|
|
4eb77c8854 | ||
|
|
839765b724 |
+2
-2
@@ -4,8 +4,8 @@ enablePlugins(AndroidGms)
|
||||
android.useSupportVectors
|
||||
|
||||
name := "shadowsocks"
|
||||
version := "4.2.0"
|
||||
versionCode := Some(190)
|
||||
version := "4.2.3"
|
||||
versionCode := Some(193)
|
||||
|
||||
proguardOptions ++=
|
||||
"-dontwarn com.google.android.gms.internal.**" ::
|
||||
|
||||
@@ -26,6 +26,8 @@ class Acl {
|
||||
@DatabaseField
|
||||
var bypass: Boolean = _
|
||||
|
||||
def isUrl(url: String): Boolean = url.startsWith("http://") || url.startsWith("https://")
|
||||
|
||||
def fromAcl(other: Acl): Acl = {
|
||||
bypassHostnames.clear()
|
||||
bypassHostnames ++= other.bypassHostnames
|
||||
@@ -49,12 +51,19 @@ class Acl {
|
||||
var hostnames: mutable.SortedList[String] = if (defaultBypass) proxyHostnames else bypassHostnames
|
||||
var subnets: mutable.SortedList[Subnet] = if (defaultBypass) proxySubnets else bypassSubnets
|
||||
var in_urls = false
|
||||
for (line <- value.getLines()) (line.indexOf('#') match {
|
||||
case -1 => if (!in_urls) line else ""
|
||||
case index =>
|
||||
if (line.contains("URLS_BEGIN")) in_urls = true
|
||||
if (line.contains("URLS_END")) in_urls = false
|
||||
line.substring(0, index) // trim comments
|
||||
for (line <- value.getLines()) (line.trim.indexOf('#') match {
|
||||
case 0 => {
|
||||
line.indexOf("NETWORK_ACL_BEGIN") match {
|
||||
case -1 =>
|
||||
case index => in_urls = true
|
||||
}
|
||||
line.indexOf("NETWORK_ACL_END") match {
|
||||
case -1 =>
|
||||
case index => in_urls = false
|
||||
}
|
||||
"" // ignore any comment lines
|
||||
}
|
||||
case index => if (!in_urls) line else ""
|
||||
}).trim match {
|
||||
case "[outbound_block_list]" =>
|
||||
hostnames = null
|
||||
@@ -68,8 +77,11 @@ class Acl {
|
||||
case "[reject_all]" | "[bypass_all]" => bypass = true
|
||||
case "[accept_all]" | "[proxy_all]" => bypass = false
|
||||
case input if subnets != null && input.nonEmpty => try subnets += Subnet.fromString(input) catch {
|
||||
case _: IllegalArgumentException => if (input.startsWith("http://") || input.startsWith("https://"))
|
||||
urls += input else hostnames += input
|
||||
case _: IllegalArgumentException => if (isUrl(input)) {
|
||||
urls += input
|
||||
} else {
|
||||
hostnames += input
|
||||
}
|
||||
}
|
||||
case _ =>
|
||||
}
|
||||
@@ -81,17 +93,16 @@ class Acl {
|
||||
def getAclString(network: Boolean): String = {
|
||||
val result = new StringBuilder()
|
||||
if (urls.nonEmpty) {
|
||||
result.append("#URLS_BEGIN\n")
|
||||
result.append(urls.mkString("\n"))
|
||||
if (network) {
|
||||
result.append("\n#NETWORK_ACL_BEGIN\n")
|
||||
try {
|
||||
urls.foreach((url: String) => result.append(Source.fromURL(url).mkString))
|
||||
} catch {
|
||||
case _: IOException => // ignore
|
||||
case e: IOException => // ignore
|
||||
}
|
||||
result.append("\n#NETWORK_ACL_END\n")
|
||||
}
|
||||
result.append("#URLS_END\n")
|
||||
|
||||
}
|
||||
if (result.isEmpty) {
|
||||
result.append(if (bypass) "[bypass_all]\n" else "[proxy_all]\n")
|
||||
@@ -112,7 +123,9 @@ class Acl {
|
||||
result.toString
|
||||
}
|
||||
|
||||
override def toString: String = getAclString(false)
|
||||
override def toString: String = {
|
||||
getAclString(false)
|
||||
}
|
||||
|
||||
def isValidCustomRules: Boolean = bypass && bypassHostnames.isEmpty
|
||||
|
||||
|
||||
@@ -125,22 +125,34 @@ class CustomRulesFragment extends ToolbarFragment with Toolbar.OnMenuItemClickLi
|
||||
})
|
||||
}
|
||||
|
||||
def getItemCount: Int = acl.subnets.size + acl.proxyHostnames.size
|
||||
def getItemCount: Int = acl.subnets.size + acl.proxyHostnames.size + acl.urls.size
|
||||
def onBindViewHolder(vh: AclRuleViewHolder, i: Int): Unit = {
|
||||
val j = i - acl.subnets.size
|
||||
if (j < 0) vh.bind(acl.subnets(i)) else vh.bind(acl.proxyHostnames(j))
|
||||
val j = i - acl.urls.size
|
||||
val k = i - acl.subnets.size - acl.urls.size
|
||||
if (j < 0)
|
||||
vh.bind(acl.urls(i))
|
||||
else if (k < 0)
|
||||
vh.bind(acl.subnets(j))
|
||||
else
|
||||
vh.bind(acl.proxyHostnames(k))
|
||||
}
|
||||
def onCreateViewHolder(vg: ViewGroup, i: Int) = new AclRuleViewHolder(LayoutInflater.from(vg.getContext)
|
||||
.inflate(android.R.layout.simple_list_item_1, vg, false))
|
||||
|
||||
def addUrl(url: String): Int = if (acl.urls.add(url)) {
|
||||
val index = acl.urls.indexOf(url)
|
||||
notifyItemInserted(index)
|
||||
apply()
|
||||
index
|
||||
} else -1
|
||||
def addSubnet(subnet: Subnet): Int = if (acl.subnets.add(subnet)) {
|
||||
val index = acl.subnets.indexOf(subnet)
|
||||
val index = acl.subnets.indexOf(subnet) + acl.urls.size
|
||||
notifyItemInserted(index)
|
||||
apply()
|
||||
index
|
||||
} else -1
|
||||
def addHostname(hostname: String): Int = if (acl.proxyHostnames.add(hostname)) {
|
||||
val index = acl.proxyHostnames.indexOf(hostname) + acl.subnets.size
|
||||
val index = acl.proxyHostnames.indexOf(hostname) + acl.urls.size + acl.subnets.size
|
||||
notifyItemInserted(index)
|
||||
apply()
|
||||
index
|
||||
@@ -148,6 +160,7 @@ class CustomRulesFragment extends ToolbarFragment with Toolbar.OnMenuItemClickLi
|
||||
def addToProxy(input: String): Int = {
|
||||
val acl = new Acl().fromSource(Source.fromString(input), defaultBypass = true)
|
||||
var result = -1
|
||||
for (url <- acl.urls) result = addUrl(url)
|
||||
for (hostname <- acl.proxyHostnames) result = addHostname(hostname)
|
||||
if (acl.bypass) for (subnet <- acl.subnets) result = addSubnet(subnet)
|
||||
result
|
||||
@@ -164,26 +177,36 @@ class CustomRulesFragment extends ToolbarFragment with Toolbar.OnMenuItemClickLi
|
||||
}
|
||||
|
||||
def remove(i: Int) {
|
||||
val j = i - acl.subnets.size
|
||||
val j = i - acl.urls.size
|
||||
val k = i - acl.urls.size - acl.subnets.size
|
||||
if (j < 0) {
|
||||
undoManager.remove((i, acl.subnets(i)))
|
||||
acl.subnets.remove(i)
|
||||
undoManager.remove((i, acl.urls(i)))
|
||||
acl.urls.remove(i)
|
||||
} else if (k < 0) {
|
||||
undoManager.remove((i, acl.subnets(j)))
|
||||
acl.subnets.remove(j)
|
||||
} else {
|
||||
undoManager.remove((j, acl.proxyHostnames(j)))
|
||||
acl.proxyHostnames.remove(j)
|
||||
undoManager.remove((i, acl.proxyHostnames(k)))
|
||||
acl.proxyHostnames.remove(k)
|
||||
}
|
||||
notifyItemRemoved(i)
|
||||
apply()
|
||||
}
|
||||
def remove(item: AnyRef): Unit = item match {
|
||||
case subnet: Subnet =>
|
||||
notifyItemRemoved(acl.subnets.indexOf(subnet))
|
||||
notifyItemRemoved(acl.subnets.indexOf(subnet) + acl.urls.size)
|
||||
acl.subnets.remove(subnet)
|
||||
apply()
|
||||
case hostname: String =>
|
||||
notifyItemRemoved(acl.proxyHostnames.indexOf(hostname))
|
||||
case hostname: String => if (acl.isUrl(hostname)) {
|
||||
notifyItemRemoved(acl.urls.indexOf(hostname))
|
||||
acl.urls.remove(hostname)
|
||||
apply()
|
||||
} else {
|
||||
notifyItemRemoved(acl.proxyHostnames.indexOf(hostname)
|
||||
+ acl.urls.size + acl.subnets.size)
|
||||
acl.proxyHostnames.remove(hostname)
|
||||
apply()
|
||||
}
|
||||
}
|
||||
def removeSelected() {
|
||||
undoManager.remove(selectedItems.map((-1, _)).toSeq: _*)
|
||||
@@ -192,12 +215,19 @@ class CustomRulesFragment extends ToolbarFragment with Toolbar.OnMenuItemClickLi
|
||||
onSelectedItemsUpdated()
|
||||
}
|
||||
def undo(actions: Iterator[(Int, AnyRef)]): Unit = for ((_, item) <- actions) item match {
|
||||
case hostname: String => if (acl.proxyHostnames.insert(hostname)) {
|
||||
notifyItemInserted(acl.proxyHostnames.indexOf(hostname) + acl.subnets.size)
|
||||
apply()
|
||||
case hostname: String => if (acl.isUrl(hostname)) {
|
||||
if (acl.urls.insert(hostname)) {
|
||||
notifyItemInserted(acl.urls.indexOf(hostname))
|
||||
apply()
|
||||
}
|
||||
} else {
|
||||
if (acl.proxyHostnames.insert(hostname)) {
|
||||
notifyItemInserted(acl.proxyHostnames.indexOf(hostname) + acl.urls.size + acl.subnets.size)
|
||||
apply()
|
||||
}
|
||||
}
|
||||
case subnet: Subnet => if (acl.subnets.insert(subnet)) {
|
||||
notifyItemInserted(acl.subnets.indexOf(subnet))
|
||||
notifyItemInserted(acl.subnets.indexOf(subnet) + acl.urls.size)
|
||||
apply()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -141,6 +141,9 @@ class DBHelper(val context: Context)
|
||||
}
|
||||
|
||||
if (oldVersion < 23) {
|
||||
profileDao.executeRawNoArgs("BEGIN TRANSACTION;")
|
||||
TableUtils.createTable(connectionSource, classOf[KeyValuePair])
|
||||
profileDao.executeRawNoArgs("COMMIT;")
|
||||
import KeyValuePair._
|
||||
val old = PreferenceManager.getDefaultSharedPreferences(app)
|
||||
kvPairDao.createOrUpdate(new KeyValuePair(Key.id, TYPE_INT,
|
||||
|
||||
Reference in New Issue
Block a user