Commit dc13249a authored by Mygod's avatar Mygod Committed by Max Lv
parent d5796606
...@@ -20,13 +20,13 @@ ...@@ -20,13 +20,13 @@
package com.github.shadowsocks.database package com.github.shadowsocks.database
import java.net.URLEncoder
import java.util.Locale import java.util.Locale
import android.content.SharedPreferences import android.content.SharedPreferences
import android.net.Uri
import android.os.Binder import android.os.Binder
import android.text.TextUtils
import android.util.Base64 import android.util.Base64
import com.github.shadowsocks.plugin.PluginConfiguration
import com.github.shadowsocks.utils.Key import com.github.shadowsocks.utils.Key
import com.j256.ormlite.field.{DataType, DatabaseField} import com.j256.ormlite.field.{DataType, DatabaseField}
...@@ -93,11 +93,19 @@ class Profile { ...@@ -93,11 +93,19 @@ class Profile {
def nameIsEmpty: Boolean = name == null || name.isEmpty def nameIsEmpty: Boolean = name == null || name.isEmpty
def getName: String = if (nameIsEmpty) formattedAddress else name def getName: String = if (nameIsEmpty) formattedAddress else name
override def toString: String = "ss://" + Base64.encodeToString("%s:%s@%s:%d".formatLocal(Locale.ENGLISH, def toUri: Uri = {
method, password, host, remotePort).getBytes, Base64.NO_PADDING | Base64.NO_WRAP) + val builder = new Uri.Builder()
(if (TextUtils.isEmpty(name)) "" else '#' + URLEncoder.encode(name, "utf-8")) .scheme("ss")
.authority("%s@%s:%d".formatLocal(Locale.ENGLISH,
def isMethodUnsafe: Boolean = "table".equalsIgnoreCase(method) || "rc4".equalsIgnoreCase(method) Base64.encodeToString("%s:%s".formatLocal(Locale.ENGLISH, method, password).getBytes,
Base64.NO_PADDING | Base64.NO_WRAP | Base64.URL_SAFE), host, remotePort))
val configuration = new PluginConfiguration(plugin)
if (configuration.selected.nonEmpty)
builder.appendQueryParameter(Key.plugin, configuration.selectedOptions.toString)
if (!nameIsEmpty) builder.fragment(name)
builder.build()
}
override def toString: String = toUri.toString
def serialize(editor: SharedPreferences.Editor): SharedPreferences.Editor = editor def serialize(editor: SharedPreferences.Editor): SharedPreferences.Editor = editor
.putString(Key.name, name) .putString(Key.name, name)
......
...@@ -20,31 +20,46 @@ ...@@ -20,31 +20,46 @@
package com.github.shadowsocks.utils package com.github.shadowsocks.utils
import java.net.URLDecoder import android.net.Uri
import android.util.Log
import android.util.{Base64, Log}
import com.github.shadowsocks.database.Profile import com.github.shadowsocks.database.Profile
object Parser { object Parser {
val TAG = "ShadowParser" val TAG = "ShadowParser"
private val pattern = "(?i)ss://([A-Za-z0-9+-/=_]+)(#(.+))?".r private val pattern = "(?i)^ss://[-a-zA-Z0-9+&@#/%?=~_|!:,.;]*[-a-zA-Z0-9+&@#/%=~_|]$".r
private val decodedPattern = "(?i)^((.+?)(-auth)??:(.*)@(.+?):(\\d+?))$".r private val userInfoPattern = "^(.+?):(.*)$".r
private val legacyPattern = "^((.+?):(.*)@(.+?):(\\d+?))$".r
def findAll(data: CharSequence): Iterator[Profile] = def findAll(data: CharSequence): Iterator[Profile] =
pattern.findAllMatchIn(if (data == null) "" else data).map(m => try pattern.findAllMatchIn(if (data == null) "" else data).map(m => {
decodedPattern.findFirstMatchIn(new String(Base64.decode(m.group(1), Base64.NO_PADDING), "UTF-8")) match { val uri = Uri.parse(m.matched)
case Some(ss) => uri.getUserInfo match {
case null => uri.getHost match {
case legacyPattern(_, method, password, host, port) => // legacy uri
val profile = new Profile
profile.method = method.toLowerCase
profile.password = password
profile.host = host
profile.remotePort = port.toInt
profile.plugin = uri.getQueryParameter(Key.plugin)
profile.name = uri.getFragment
profile
case _ =>
Log.e(TAG, "Unrecognized URI: " + m.matched)
null
}
case userInfoPattern(method, password) =>
val profile = new Profile val profile = new Profile
profile.method = ss.group(2).toLowerCase profile.method = method
profile.password = ss.group(4) profile.password = password
profile.host = ss.group(5) profile.host = uri.getHost
profile.remotePort = ss.group(6).toInt profile.remotePort = uri.getPort
if (m.group(2) != null) profile.name = URLDecoder.decode(m.group(3), "utf-8") profile.plugin = uri.getQueryParameter(Key.plugin)
profile.name = uri.getFragment
profile profile
case _ => null case _ =>
} catch { Log.e(TAG, "Unknown user info: " + m.matched)
case ex: Exception =>
Log.e(TAG, "parser error: " + m.source, ex)// Ignore
null null
}).filter(_ != null) }
}).filter(_ != null)
} }
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